mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
Merge
This commit is contained in:
commit
f5750b67fd
74 changed files with 3880 additions and 508 deletions
|
@ -59,7 +59,7 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
|
||||||
_has_nonstatic_fields = ik->has_nonstatic_fields();
|
_has_nonstatic_fields = ik->has_nonstatic_fields();
|
||||||
_has_default_methods = ik->has_default_methods();
|
_has_default_methods = ik->has_default_methods();
|
||||||
_nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
|
_nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
|
||||||
|
_has_injected_fields = -1;
|
||||||
_implementor = NULL; // we will fill these lazily
|
_implementor = NULL; // we will fill these lazily
|
||||||
|
|
||||||
Thread *thread = Thread::current();
|
Thread *thread = Thread::current();
|
||||||
|
@ -100,6 +100,7 @@ ciInstanceKlass::ciInstanceKlass(ciSymbol* name,
|
||||||
_nonstatic_field_size = -1;
|
_nonstatic_field_size = -1;
|
||||||
_has_nonstatic_fields = false;
|
_has_nonstatic_fields = false;
|
||||||
_nonstatic_fields = NULL;
|
_nonstatic_fields = NULL;
|
||||||
|
_has_injected_fields = -1;
|
||||||
_loader = loader;
|
_loader = loader;
|
||||||
_protection_domain = protection_domain;
|
_protection_domain = protection_domain;
|
||||||
_is_shared = false;
|
_is_shared = false;
|
||||||
|
@ -500,6 +501,34 @@ ciInstanceKlass::compute_nonstatic_fields_impl(GrowableArray<ciField*>*
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ciInstanceKlass::compute_injected_fields_helper() {
|
||||||
|
ASSERT_IN_VM;
|
||||||
|
InstanceKlass* k = get_instanceKlass();
|
||||||
|
|
||||||
|
for (InternalFieldStream fs(k); !fs.done(); fs.next()) {
|
||||||
|
if (fs.access_flags().is_static()) continue;
|
||||||
|
_has_injected_fields++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ciInstanceKlass::compute_injected_fields() {
|
||||||
|
assert(_has_injected_fields == -1, "shouldn't be initialized yet");
|
||||||
|
assert(is_loaded(), "must be loaded");
|
||||||
|
|
||||||
|
if (super() != NULL && super()->has_injected_fields()) {
|
||||||
|
_has_injected_fields = 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_has_injected_fields = 0;
|
||||||
|
GUARDED_VM_ENTRY({
|
||||||
|
compute_injected_fields_helper();
|
||||||
|
});
|
||||||
|
|
||||||
|
return _has_injected_fields > 0 ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciInstanceKlass::find_method
|
// ciInstanceKlass::find_method
|
||||||
//
|
//
|
||||||
|
|
|
@ -64,6 +64,7 @@ private:
|
||||||
|
|
||||||
ciConstantPoolCache* _field_cache; // cached map index->field
|
ciConstantPoolCache* _field_cache; // cached map index->field
|
||||||
GrowableArray<ciField*>* _nonstatic_fields;
|
GrowableArray<ciField*>* _nonstatic_fields;
|
||||||
|
int _has_injected_fields; // any non static injected fields? lazily initialized.
|
||||||
|
|
||||||
// The possible values of the _implementor fall into following three cases:
|
// The possible values of the _implementor fall into following three cases:
|
||||||
// NULL: no implementor.
|
// NULL: no implementor.
|
||||||
|
@ -71,6 +72,9 @@ private:
|
||||||
// Itsef: more than one implementors.
|
// Itsef: more than one implementors.
|
||||||
ciInstanceKlass* _implementor;
|
ciInstanceKlass* _implementor;
|
||||||
|
|
||||||
|
bool compute_injected_fields();
|
||||||
|
void compute_injected_fields_helper();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ciInstanceKlass(KlassHandle h_k);
|
ciInstanceKlass(KlassHandle h_k);
|
||||||
ciInstanceKlass(ciSymbol* name, jobject loader, jobject protection_domain);
|
ciInstanceKlass(ciSymbol* name, jobject loader, jobject protection_domain);
|
||||||
|
@ -186,6 +190,14 @@ public:
|
||||||
else
|
else
|
||||||
return _nonstatic_fields->length();
|
return _nonstatic_fields->length();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool has_injected_fields() {
|
||||||
|
if (_has_injected_fields == -1) {
|
||||||
|
return compute_injected_fields();
|
||||||
|
}
|
||||||
|
return _has_injected_fields > 0 ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
// nth nonstatic field (presented by ascending address)
|
// nth nonstatic field (presented by ascending address)
|
||||||
ciField* nonstatic_field_at(int i) {
|
ciField* nonstatic_field_at(int i) {
|
||||||
assert(_nonstatic_fields != NULL, "");
|
assert(_nonstatic_fields != NULL, "");
|
||||||
|
|
|
@ -51,7 +51,7 @@ class FieldStreamBase : public StackObj {
|
||||||
|
|
||||||
int init_generic_signature_start_slot() {
|
int init_generic_signature_start_slot() {
|
||||||
int length = _fields->length();
|
int length = _fields->length();
|
||||||
int num_fields = 0;
|
int num_fields = _index;
|
||||||
int skipped_generic_signature_slots = 0;
|
int skipped_generic_signature_slots = 0;
|
||||||
FieldInfo* fi;
|
FieldInfo* fi;
|
||||||
AccessFlags flags;
|
AccessFlags flags;
|
||||||
|
|
|
@ -669,6 +669,13 @@
|
||||||
product_pd(bool, TrapBasedRangeChecks, \
|
product_pd(bool, TrapBasedRangeChecks, \
|
||||||
"Generate code for range checks that uses a cmp and trap " \
|
"Generate code for range checks that uses a cmp and trap " \
|
||||||
"instruction raising SIGTRAP. Used on PPC64.") \
|
"instruction raising SIGTRAP. Used on PPC64.") \
|
||||||
|
\
|
||||||
|
product(intx, ArrayCopyLoadStoreMaxElem, 8, \
|
||||||
|
"Maximum number of arraycopy elements inlined as a sequence of" \
|
||||||
|
"loads/stores") \
|
||||||
|
\
|
||||||
|
develop(bool, StressArrayCopyMacroNode, false, \
|
||||||
|
"Perform ArrayCopy load/store replacement during IGVN only")
|
||||||
|
|
||||||
C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG)
|
C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG)
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,9 @@ const char* C2Compiler::retry_no_subsuming_loads() {
|
||||||
const char* C2Compiler::retry_no_escape_analysis() {
|
const char* C2Compiler::retry_no_escape_analysis() {
|
||||||
return "retry without escape analysis";
|
return "retry without escape analysis";
|
||||||
}
|
}
|
||||||
|
const char* C2Compiler::retry_class_loading_during_parsing() {
|
||||||
|
return "retry class loading during parsing";
|
||||||
|
}
|
||||||
bool C2Compiler::init_c2_runtime() {
|
bool C2Compiler::init_c2_runtime() {
|
||||||
|
|
||||||
// Check assumptions used while running ADLC
|
// Check assumptions used while running ADLC
|
||||||
|
@ -104,6 +107,10 @@ void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
|
||||||
|
|
||||||
// Check result and retry if appropriate.
|
// Check result and retry if appropriate.
|
||||||
if (C.failure_reason() != NULL) {
|
if (C.failure_reason() != NULL) {
|
||||||
|
if (C.failure_reason_is(retry_class_loading_during_parsing())) {
|
||||||
|
env->report_failure(C.failure_reason());
|
||||||
|
continue; // retry
|
||||||
|
}
|
||||||
if (C.failure_reason_is(retry_no_subsuming_loads())) {
|
if (C.failure_reason_is(retry_no_subsuming_loads())) {
|
||||||
assert(subsume_loads, "must make progress");
|
assert(subsume_loads, "must make progress");
|
||||||
subsume_loads = false;
|
subsume_loads = false;
|
||||||
|
|
|
@ -47,6 +47,7 @@ public:
|
||||||
// sentinel value used to trigger backtracking in compile_method().
|
// sentinel value used to trigger backtracking in compile_method().
|
||||||
static const char* retry_no_subsuming_loads();
|
static const char* retry_no_subsuming_loads();
|
||||||
static const char* retry_no_escape_analysis();
|
static const char* retry_no_escape_analysis();
|
||||||
|
static const char* retry_class_loading_during_parsing();
|
||||||
|
|
||||||
// Print compilation timers and statistics
|
// Print compilation timers and statistics
|
||||||
void print_timers();
|
void print_timers();
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "opto/callGenerator.hpp"
|
#include "opto/callGenerator.hpp"
|
||||||
#include "opto/callnode.hpp"
|
#include "opto/callnode.hpp"
|
||||||
#include "opto/castnode.hpp"
|
#include "opto/castnode.hpp"
|
||||||
|
#include "opto/convertnode.hpp"
|
||||||
#include "opto/escape.hpp"
|
#include "opto/escape.hpp"
|
||||||
#include "opto/locknode.hpp"
|
#include "opto/locknode.hpp"
|
||||||
#include "opto/machnode.hpp"
|
#include "opto/machnode.hpp"
|
||||||
|
@ -1818,7 +1819,10 @@ Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayCopyNode::ArrayCopyNode(Compile* C, bool alloc_tightly_coupled)
|
ArrayCopyNode::ArrayCopyNode(Compile* C, bool alloc_tightly_coupled)
|
||||||
: CallNode(arraycopy_type(), NULL, TypeRawPtr::BOTTOM), _alloc_tightly_coupled(alloc_tightly_coupled), _kind(ArrayCopy) {
|
: CallNode(arraycopy_type(), NULL, TypeRawPtr::BOTTOM),
|
||||||
|
_alloc_tightly_coupled(alloc_tightly_coupled),
|
||||||
|
_kind(None),
|
||||||
|
_arguments_validated(false) {
|
||||||
init_class_id(Class_ArrayCopy);
|
init_class_id(Class_ArrayCopy);
|
||||||
init_flags(Flag_is_macro);
|
init_flags(Flag_is_macro);
|
||||||
C->add_macro_node(this);
|
C->add_macro_node(this);
|
||||||
|
@ -1870,3 +1874,136 @@ void ArrayCopyNode::dump_spec(outputStream *st) const {
|
||||||
st->print(" (%s%s)", _kind_names[_kind], _alloc_tightly_coupled ? ", tightly coupled allocation" : "");
|
st->print(" (%s%s)", _kind_names[_kind], _alloc_tightly_coupled ? ", tightly coupled allocation" : "");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int ArrayCopyNode::get_count(PhaseGVN *phase) const {
|
||||||
|
Node* src = in(ArrayCopyNode::Src);
|
||||||
|
const Type* src_type = phase->type(src);
|
||||||
|
|
||||||
|
assert(is_clonebasic(), "unexpected arraycopy type");
|
||||||
|
if (src_type->isa_instptr()) {
|
||||||
|
const TypeInstPtr* inst_src = src_type->is_instptr();
|
||||||
|
ciInstanceKlass* ik = inst_src->klass()->as_instance_klass();
|
||||||
|
// ciInstanceKlass::nof_nonstatic_fields() doesn't take injected
|
||||||
|
// fields into account. They are rare anyway so easier to simply
|
||||||
|
// skip instances with injected fields.
|
||||||
|
if ((!inst_src->klass_is_exact() && (ik->is_interface() || ik->has_subklass())) || ik->has_injected_fields()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int nb_fields = ik->nof_nonstatic_fields();
|
||||||
|
return nb_fields;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* ArrayCopyNode::try_clone_instance(PhaseGVN *phase, bool can_reshape, int count) {
|
||||||
|
assert(is_clonebasic(), "unexpected arraycopy type");
|
||||||
|
|
||||||
|
Node* src = in(ArrayCopyNode::Src);
|
||||||
|
Node* dest = in(ArrayCopyNode::Dest);
|
||||||
|
Node* ctl = in(TypeFunc::Control);
|
||||||
|
Node* in_mem = in(TypeFunc::Memory);
|
||||||
|
|
||||||
|
const Type* src_type = phase->type(src);
|
||||||
|
const Type* dest_type = phase->type(dest);
|
||||||
|
|
||||||
|
assert(src->is_AddP(), "should be base + off");
|
||||||
|
assert(dest->is_AddP(), "should be base + off");
|
||||||
|
Node* base_src = src->in(AddPNode::Base);
|
||||||
|
Node* base_dest = dest->in(AddPNode::Base);
|
||||||
|
|
||||||
|
MergeMemNode* mem = MergeMemNode::make(in_mem);
|
||||||
|
|
||||||
|
const TypeInstPtr* inst_src = src_type->is_instptr();
|
||||||
|
|
||||||
|
if (!inst_src->klass_is_exact()) {
|
||||||
|
ciInstanceKlass* ik = inst_src->klass()->as_instance_klass();
|
||||||
|
assert(!ik->is_interface() && !ik->has_subklass(), "inconsistent klass hierarchy");
|
||||||
|
phase->C->dependencies()->assert_leaf_type(ik);
|
||||||
|
}
|
||||||
|
|
||||||
|
ciInstanceKlass* ik = inst_src->klass()->as_instance_klass();
|
||||||
|
assert(ik->nof_nonstatic_fields() <= ArrayCopyLoadStoreMaxElem, "too many fields");
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
ciField* field = ik->nonstatic_field_at(i);
|
||||||
|
int fieldidx = phase->C->alias_type(field)->index();
|
||||||
|
const TypePtr* adr_type = phase->C->alias_type(field)->adr_type();
|
||||||
|
Node* off = phase->MakeConX(field->offset());
|
||||||
|
Node* next_src = phase->transform(new AddPNode(base_src,base_src,off));
|
||||||
|
Node* next_dest = phase->transform(new AddPNode(base_dest,base_dest,off));
|
||||||
|
BasicType bt = field->layout_type();
|
||||||
|
|
||||||
|
const Type *type;
|
||||||
|
if (bt == T_OBJECT) {
|
||||||
|
if (!field->type()->is_loaded()) {
|
||||||
|
type = TypeInstPtr::BOTTOM;
|
||||||
|
} else {
|
||||||
|
ciType* field_klass = field->type();
|
||||||
|
type = TypeOopPtr::make_from_klass(field_klass->as_klass());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
type = Type::get_const_basic_type(bt);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* v = LoadNode::make(*phase, ctl, mem->memory_at(fieldidx), next_src, adr_type, type, bt, MemNode::unordered);
|
||||||
|
v = phase->transform(v);
|
||||||
|
Node* s = StoreNode::make(*phase, ctl, mem->memory_at(fieldidx), next_dest, adr_type, v, bt, MemNode::unordered);
|
||||||
|
s = phase->transform(s);
|
||||||
|
mem->set_memory_at(fieldidx, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!finish_transform(phase, can_reshape, ctl, mem)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArrayCopyNode::finish_transform(PhaseGVN *phase, bool can_reshape,
|
||||||
|
Node* ctl, Node *mem) {
|
||||||
|
if (can_reshape) {
|
||||||
|
PhaseIterGVN* igvn = phase->is_IterGVN();
|
||||||
|
assert(is_clonebasic(), "unexpected arraycopy type");
|
||||||
|
Node* out_mem = proj_out(TypeFunc::Memory);
|
||||||
|
|
||||||
|
if (out_mem->outcnt() != 1 || !out_mem->raw_out(0)->is_MergeMem() ||
|
||||||
|
out_mem->raw_out(0)->outcnt() != 1 || !out_mem->raw_out(0)->raw_out(0)->is_MemBar()) {
|
||||||
|
assert(!GraphKit::use_ReduceInitialCardMarks(), "can only happen with card marking");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
igvn->replace_node(out_mem->raw_out(0), mem);
|
||||||
|
|
||||||
|
Node* out_ctl = proj_out(TypeFunc::Control);
|
||||||
|
igvn->replace_node(out_ctl, ctl);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Node *ArrayCopyNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||||
|
|
||||||
|
if (StressArrayCopyMacroNode && !can_reshape) return NULL;
|
||||||
|
|
||||||
|
// See if it's a small array copy and we can inline it as
|
||||||
|
// loads/stores
|
||||||
|
// Here we can only do:
|
||||||
|
// - clone for which we don't need to do card marking
|
||||||
|
|
||||||
|
if (!is_clonebasic()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in(TypeFunc::Control)->is_top() || in(TypeFunc::Memory)->is_top()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = get_count(phase);
|
||||||
|
|
||||||
|
if (count < 0 || count > ArrayCopyLoadStoreMaxElem) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* mem = try_clone_instance(phase, can_reshape, count);
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
|
@ -1070,8 +1070,8 @@ private:
|
||||||
|
|
||||||
// What kind of arraycopy variant is this?
|
// What kind of arraycopy variant is this?
|
||||||
enum {
|
enum {
|
||||||
|
None, // not set yet
|
||||||
ArrayCopy, // System.arraycopy()
|
ArrayCopy, // System.arraycopy()
|
||||||
ArrayCopyNoTest, // System.arraycopy(), all arguments validated
|
|
||||||
CloneBasic, // A clone that can be copied by 64 bit chunks
|
CloneBasic, // A clone that can be copied by 64 bit chunks
|
||||||
CloneOop, // An oop array clone
|
CloneOop, // An oop array clone
|
||||||
CopyOf, // Arrays.copyOf()
|
CopyOf, // Arrays.copyOf()
|
||||||
|
@ -1095,6 +1095,8 @@ private:
|
||||||
// LibraryCallKit::tightly_coupled_allocation() is called.
|
// LibraryCallKit::tightly_coupled_allocation() is called.
|
||||||
bool _alloc_tightly_coupled;
|
bool _alloc_tightly_coupled;
|
||||||
|
|
||||||
|
bool _arguments_validated;
|
||||||
|
|
||||||
static const TypeFunc* arraycopy_type() {
|
static const TypeFunc* arraycopy_type() {
|
||||||
const Type** fields = TypeTuple::fields(ParmLimit - TypeFunc::Parms);
|
const Type** fields = TypeTuple::fields(ParmLimit - TypeFunc::Parms);
|
||||||
fields[Src] = TypeInstPtr::BOTTOM;
|
fields[Src] = TypeInstPtr::BOTTOM;
|
||||||
|
@ -1118,6 +1120,13 @@ private:
|
||||||
|
|
||||||
ArrayCopyNode(Compile* C, bool alloc_tightly_coupled);
|
ArrayCopyNode(Compile* C, bool alloc_tightly_coupled);
|
||||||
|
|
||||||
|
int get_count(PhaseGVN *phase) const;
|
||||||
|
static const TypePtr* get_address_type(PhaseGVN *phase, Node* n);
|
||||||
|
|
||||||
|
Node* try_clone_instance(PhaseGVN *phase, bool can_reshape, int count);
|
||||||
|
bool finish_transform(PhaseGVN *phase, bool can_reshape,
|
||||||
|
Node* ctl, Node *mem);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -1143,23 +1152,23 @@ public:
|
||||||
|
|
||||||
void connect_outputs(GraphKit* kit);
|
void connect_outputs(GraphKit* kit);
|
||||||
|
|
||||||
bool is_arraycopy() const { return _kind == ArrayCopy; }
|
bool is_arraycopy() const { assert(_kind != None, "should bet set"); return _kind == ArrayCopy; }
|
||||||
bool is_arraycopy_notest() const { return _kind == ArrayCopyNoTest; }
|
bool is_arraycopy_validated() const { assert(_kind != None, "should bet set"); return _kind == ArrayCopy && _arguments_validated; }
|
||||||
bool is_clonebasic() const { return _kind == CloneBasic; }
|
bool is_clonebasic() const { assert(_kind != None, "should bet set"); return _kind == CloneBasic; }
|
||||||
bool is_cloneoop() const { return _kind == CloneOop; }
|
bool is_cloneoop() const { assert(_kind != None, "should bet set"); return _kind == CloneOop; }
|
||||||
bool is_copyof() const { return _kind == CopyOf; }
|
bool is_copyof() const { assert(_kind != None, "should bet set"); return _kind == CopyOf; }
|
||||||
bool is_copyofrange() const { return _kind == CopyOfRange; }
|
bool is_copyofrange() const { assert(_kind != None, "should bet set"); return _kind == CopyOfRange; }
|
||||||
|
|
||||||
void set_arraycopy() { _kind = ArrayCopy; }
|
void set_arraycopy(bool validated) { assert(_kind == None, "shouldn't bet set yet"); _kind = ArrayCopy; _arguments_validated = validated; }
|
||||||
void set_arraycopy_notest() { _kind = ArrayCopyNoTest; }
|
void set_clonebasic() { assert(_kind == None, "shouldn't bet set yet"); _kind = CloneBasic; }
|
||||||
void set_clonebasic() { _kind = CloneBasic; }
|
void set_cloneoop() { assert(_kind == None, "shouldn't bet set yet"); _kind = CloneOop; }
|
||||||
void set_cloneoop() { _kind = CloneOop; }
|
void set_copyof() { assert(_kind == None, "shouldn't bet set yet"); _kind = CopyOf; _arguments_validated = false; }
|
||||||
void set_copyof() { _kind = CopyOf; }
|
void set_copyofrange() { assert(_kind == None, "shouldn't bet set yet"); _kind = CopyOfRange; _arguments_validated = false; }
|
||||||
void set_copyofrange() { _kind = CopyOfRange; }
|
|
||||||
|
|
||||||
virtual int Opcode() const;
|
virtual int Opcode() const;
|
||||||
virtual uint size_of() const; // Size is bigger
|
virtual uint size_of() const; // Size is bigger
|
||||||
virtual bool guaranteed_safepoint() { return false; }
|
virtual bool guaranteed_safepoint() { return false; }
|
||||||
|
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||||
|
|
||||||
bool is_alloc_tightly_coupled() const { return _alloc_tightly_coupled; }
|
bool is_alloc_tightly_coupled() const { return _alloc_tightly_coupled; }
|
||||||
|
|
||||||
|
|
|
@ -774,7 +774,9 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||||
}
|
}
|
||||||
JVMState* jvms = build_start_state(start(), tf());
|
JVMState* jvms = build_start_state(start(), tf());
|
||||||
if ((jvms = cg->generate(jvms)) == NULL) {
|
if ((jvms = cg->generate(jvms)) == NULL) {
|
||||||
|
if (!failure_reason_is(C2Compiler::retry_class_loading_during_parsing())) {
|
||||||
record_method_not_compilable("method parse failed");
|
record_method_not_compilable("method parse failed");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GraphKit kit(jvms);
|
GraphKit kit(jvms);
|
||||||
|
|
|
@ -4475,8 +4475,11 @@ void LibraryCallKit::copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, b
|
||||||
ArrayCopyNode* ac = ArrayCopyNode::make(this, false, src, NULL, dest, NULL, countx, false);
|
ArrayCopyNode* ac = ArrayCopyNode::make(this, false, src, NULL, dest, NULL, countx, false);
|
||||||
ac->set_clonebasic();
|
ac->set_clonebasic();
|
||||||
Node* n = _gvn.transform(ac);
|
Node* n = _gvn.transform(ac);
|
||||||
assert(n == ac, "cannot disappear");
|
if (n == ac) {
|
||||||
set_predefined_output_for_runtime_call(ac, ac->in(TypeFunc::Memory), raw_adr_type);
|
set_predefined_output_for_runtime_call(ac, ac->in(TypeFunc::Memory), raw_adr_type);
|
||||||
|
} else {
|
||||||
|
set_all_memory(n);
|
||||||
|
}
|
||||||
|
|
||||||
// If necessary, emit some card marks afterwards. (Non-arrays only.)
|
// If necessary, emit some card marks afterwards. (Non-arrays only.)
|
||||||
if (card_mark) {
|
if (card_mark) {
|
||||||
|
@ -4541,6 +4544,26 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
|
||||||
Node* obj = null_check_receiver();
|
Node* obj = null_check_receiver();
|
||||||
if (stopped()) return true;
|
if (stopped()) return true;
|
||||||
|
|
||||||
|
const TypeOopPtr* obj_type = _gvn.type(obj)->is_oopptr();
|
||||||
|
|
||||||
|
// If we are going to clone an instance, we need its exact type to
|
||||||
|
// know the number and types of fields to convert the clone to
|
||||||
|
// loads/stores. Maybe a speculative type can help us.
|
||||||
|
if (!obj_type->klass_is_exact() &&
|
||||||
|
obj_type->speculative_type() != NULL &&
|
||||||
|
obj_type->speculative_type()->is_instance_klass()) {
|
||||||
|
ciInstanceKlass* spec_ik = obj_type->speculative_type()->as_instance_klass();
|
||||||
|
if (spec_ik->nof_nonstatic_fields() <= ArrayCopyLoadStoreMaxElem &&
|
||||||
|
!spec_ik->has_injected_fields()) {
|
||||||
|
ciKlass* k = obj_type->klass();
|
||||||
|
if (!k->is_instance_klass() ||
|
||||||
|
k->as_instance_klass()->is_interface() ||
|
||||||
|
k->as_instance_klass()->has_subklass()) {
|
||||||
|
obj = maybe_cast_profiled_obj(obj, obj_type->speculative_type(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Node* obj_klass = load_object_klass(obj);
|
Node* obj_klass = load_object_klass(obj);
|
||||||
const TypeKlassPtr* tklass = _gvn.type(obj_klass)->isa_klassptr();
|
const TypeKlassPtr* tklass = _gvn.type(obj_klass)->isa_klassptr();
|
||||||
const TypeOopPtr* toop = ((tklass != NULL)
|
const TypeOopPtr* toop = ((tklass != NULL)
|
||||||
|
@ -4743,7 +4766,7 @@ bool LibraryCallKit::inline_arraycopy() {
|
||||||
sfpt->set_memory(map()->memory());
|
sfpt->set_memory(map()->memory());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool notest = false;
|
bool validated = false;
|
||||||
|
|
||||||
const Type* src_type = _gvn.type(src);
|
const Type* src_type = _gvn.type(src);
|
||||||
const Type* dest_type = _gvn.type(dest);
|
const Type* dest_type = _gvn.type(dest);
|
||||||
|
@ -4847,7 +4870,7 @@ bool LibraryCallKit::inline_arraycopy() {
|
||||||
|
|
||||||
if (!too_many_traps(Deoptimization::Reason_intrinsic) && !src->is_top() && !dest->is_top()) {
|
if (!too_many_traps(Deoptimization::Reason_intrinsic) && !src->is_top() && !dest->is_top()) {
|
||||||
// validate arguments: enables transformation the ArrayCopyNode
|
// validate arguments: enables transformation the ArrayCopyNode
|
||||||
notest = true;
|
validated = true;
|
||||||
|
|
||||||
RegionNode* slow_region = new RegionNode(1);
|
RegionNode* slow_region = new RegionNode(1);
|
||||||
record_for_igvn(slow_region);
|
record_for_igvn(slow_region);
|
||||||
|
@ -4922,13 +4945,15 @@ bool LibraryCallKit::inline_arraycopy() {
|
||||||
load_object_klass(src), load_object_klass(dest),
|
load_object_klass(src), load_object_klass(dest),
|
||||||
load_array_length(src), load_array_length(dest));
|
load_array_length(src), load_array_length(dest));
|
||||||
|
|
||||||
if (notest) {
|
ac->set_arraycopy(validated);
|
||||||
ac->set_arraycopy_notest();
|
|
||||||
}
|
|
||||||
|
|
||||||
Node* n = _gvn.transform(ac);
|
Node* n = _gvn.transform(ac);
|
||||||
assert(n == ac, "cannot disappear");
|
if (n == ac) {
|
||||||
ac->connect_outputs(this);
|
ac->connect_outputs(this);
|
||||||
|
} else {
|
||||||
|
assert(validated, "shouldn't transform if all arguments not validated");
|
||||||
|
set_all_memory(n);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -519,7 +519,8 @@ Node* PhaseMacroExpand::generate_arraycopy(ArrayCopyNode *ac, AllocateArrayNode*
|
||||||
// Test S[] against D[], not S against D, because (probably)
|
// Test S[] against D[], not S against D, because (probably)
|
||||||
// the secondary supertype cache is less busy for S[] than S.
|
// the secondary supertype cache is less busy for S[] than S.
|
||||||
// This usually only matters when D is an interface.
|
// This usually only matters when D is an interface.
|
||||||
Node* not_subtype_ctrl = ac->is_arraycopy_notest() ? top() : Phase::gen_subtype_check(src_klass, dest_klass, ctrl, mem, &_igvn);
|
Node* not_subtype_ctrl = ac->is_arraycopy_validated() ? top() :
|
||||||
|
Phase::gen_subtype_check(src_klass, dest_klass, ctrl, mem, &_igvn);
|
||||||
// Plug failing path into checked_oop_disjoint_arraycopy
|
// Plug failing path into checked_oop_disjoint_arraycopy
|
||||||
if (not_subtype_ctrl != top()) {
|
if (not_subtype_ctrl != top()) {
|
||||||
Node* local_ctrl = not_subtype_ctrl;
|
Node* local_ctrl = not_subtype_ctrl;
|
||||||
|
@ -1109,7 +1110,7 @@ void PhaseMacroExpand::expand_arraycopy_node(ArrayCopyNode *ac) {
|
||||||
assert(alloc != NULL, "expect alloc");
|
assert(alloc != NULL, "expect alloc");
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(ac->is_arraycopy() || ac->is_arraycopy_notest(), "should be an arraycopy");
|
assert(ac->is_arraycopy() || ac->is_arraycopy_validated(), "should be an arraycopy");
|
||||||
|
|
||||||
// Compile time checks. If any of these checks cannot be verified at compile time,
|
// Compile time checks. If any of these checks cannot be verified at compile time,
|
||||||
// we do not make a fast path for this call. Instead, we let the call remain as it
|
// we do not make a fast path for this call. Instead, we let the call remain as it
|
||||||
|
@ -1191,7 +1192,7 @@ void PhaseMacroExpand::expand_arraycopy_node(ArrayCopyNode *ac) {
|
||||||
RegionNode* slow_region = new RegionNode(1);
|
RegionNode* slow_region = new RegionNode(1);
|
||||||
transform_later(slow_region);
|
transform_later(slow_region);
|
||||||
|
|
||||||
if (!ac->is_arraycopy_notest()) {
|
if (!ac->is_arraycopy_validated()) {
|
||||||
// (3) operands must not be null
|
// (3) operands must not be null
|
||||||
// We currently perform our null checks with the null_check routine.
|
// We currently perform our null checks with the null_check routine.
|
||||||
// This means that the null exceptions will be reported in the caller
|
// This means that the null exceptions will be reported in the caller
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "interpreter/linkResolver.hpp"
|
#include "interpreter/linkResolver.hpp"
|
||||||
#include "oops/method.hpp"
|
#include "oops/method.hpp"
|
||||||
#include "opto/addnode.hpp"
|
#include "opto/addnode.hpp"
|
||||||
|
#include "opto/c2compiler.hpp"
|
||||||
#include "opto/castnode.hpp"
|
#include "opto/castnode.hpp"
|
||||||
#include "opto/idealGraphPrinter.hpp"
|
#include "opto/idealGraphPrinter.hpp"
|
||||||
#include "opto/locknode.hpp"
|
#include "opto/locknode.hpp"
|
||||||
|
@ -986,7 +987,18 @@ void Parse::do_exits() {
|
||||||
if (tf()->range()->cnt() > TypeFunc::Parms) {
|
if (tf()->range()->cnt() > TypeFunc::Parms) {
|
||||||
const Type* ret_type = tf()->range()->field_at(TypeFunc::Parms);
|
const Type* ret_type = tf()->range()->field_at(TypeFunc::Parms);
|
||||||
Node* ret_phi = _gvn.transform( _exits.argument(0) );
|
Node* ret_phi = _gvn.transform( _exits.argument(0) );
|
||||||
assert(_exits.control()->is_top() || !_gvn.type(ret_phi)->empty(), "return value must be well defined");
|
if (!_exits.control()->is_top() && _gvn.type(ret_phi)->empty()) {
|
||||||
|
// In case of concurrent class loading, the type we set for the
|
||||||
|
// ret_phi in build_exits() may have been too optimistic and the
|
||||||
|
// ret_phi may be top now.
|
||||||
|
#ifdef ASSERT
|
||||||
|
{
|
||||||
|
MutexLockerEx ml(Compile_lock, Mutex::_no_safepoint_check_flag);
|
||||||
|
assert(ret_type->isa_ptr() && C->env()->system_dictionary_modification_counter_changed(), "return value must be well defined");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
C->record_failure(C2Compiler::retry_class_loading_during_parsing());
|
||||||
|
}
|
||||||
_exits.push_node(ret_type->basic_type(), ret_phi);
|
_exits.push_node(ret_type->basic_type(), ret_phi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1123,6 +1123,16 @@ WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean
|
||||||
attemptedNoSafepointValue == JNI_TRUE);
|
attemptedNoSafepointValue == JNI_TRUE);
|
||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
|
||||||
|
oop obj_oop = JNIHandles::resolve(obj);
|
||||||
|
return (jboolean) obj_oop->mark()->has_monitor();
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(void, WB_ForceSafepoint(JNIEnv* env, jobject wb))
|
||||||
|
VM_ForceSafepoint force_safepoint_op;
|
||||||
|
VMThread::execute(&force_safepoint_op);
|
||||||
|
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) {
|
||||||
|
@ -1321,6 +1331,8 @@ static JNINativeMethod methods[] = {
|
||||||
{CC"getThreadStackSize", CC"()J", (void*)&WB_GetThreadStackSize },
|
{CC"getThreadStackSize", CC"()J", (void*)&WB_GetThreadStackSize },
|
||||||
{CC"getThreadRemainingStackSize", CC"()J", (void*)&WB_GetThreadRemainingStackSize },
|
{CC"getThreadRemainingStackSize", CC"()J", (void*)&WB_GetThreadRemainingStackSize },
|
||||||
{CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls },
|
{CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls },
|
||||||
|
{CC"isMonitorInflated", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated },
|
||||||
|
{CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint },
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef CC
|
#undef CC
|
||||||
|
|
|
@ -145,6 +145,7 @@ needs_compact3 = \
|
||||||
gc/survivorAlignment \
|
gc/survivorAlignment \
|
||||||
runtime/InternalApi/ThreadCpuTimesDeadlock.java \
|
runtime/InternalApi/ThreadCpuTimesDeadlock.java \
|
||||||
serviceability/threads/TestFalseDeadLock.java \
|
serviceability/threads/TestFalseDeadLock.java \
|
||||||
|
compiler/codecache/jmx
|
||||||
|
|
||||||
# Compact 2 adds full VM tests
|
# Compact 2 adds full VM tests
|
||||||
compact2 = \
|
compact2 = \
|
||||||
|
|
79
hotspot/test/compiler/arraycopy/TestArrayCopyMacro.java
Normal file
79
hotspot/test/compiler/arraycopy/TestArrayCopyMacro.java
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015, 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 7173584
|
||||||
|
* @summary arraycopy as macro node
|
||||||
|
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestArrayCopyMacro
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class TestArrayCopyMacro {
|
||||||
|
static class A {
|
||||||
|
}
|
||||||
|
|
||||||
|
// In its own method so profiling reports both branches taken
|
||||||
|
static Object m2(Object o1, Object o2, int i) {
|
||||||
|
if (i == 4) {
|
||||||
|
return o1;
|
||||||
|
}
|
||||||
|
return o2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Object m1(A[] src, Object dest) {
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
|
// won't be optimized out until after parsing
|
||||||
|
for (; i < 3; i *= 4) {
|
||||||
|
}
|
||||||
|
dest = m2(new A[10], dest, i);
|
||||||
|
|
||||||
|
// dest is new array here but C2 picks the "disjoint" stub
|
||||||
|
// only if stub to call is decided after parsing
|
||||||
|
System.arraycopy(src, 0, dest, 0, 10);
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
A[] array_src = new A[10];
|
||||||
|
|
||||||
|
for (int i = 0; i < array_src.length; i++) {
|
||||||
|
array_src[i] = new A();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 20000; i++) {
|
||||||
|
m2(null, null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 20000; i++) {
|
||||||
|
Object[] array_dest = (Object[])m1(array_src, null);
|
||||||
|
|
||||||
|
for (int j = 0; j < array_src.length; j++) {
|
||||||
|
if (array_dest[j] != array_src[j]) {
|
||||||
|
throw new RuntimeException("copy failed at index " + j + " src = " + array_src[j] + " dest = " + array_dest[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,13 +25,13 @@
|
||||||
* @test
|
* @test
|
||||||
* @bug 8055910
|
* @bug 8055910
|
||||||
* @summary Arrays.copyOf doesn't perform subtype check
|
* @summary Arrays.copyOf doesn't perform subtype check
|
||||||
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestArrayOfNoTypeCheck
|
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestArraysCopyOfNoTypeCheck
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class TestArrayOfNoTypeCheck {
|
public class TestArraysCopyOfNoTypeCheck {
|
||||||
|
|
||||||
static class A {
|
static class A {
|
||||||
}
|
}
|
|
@ -0,0 +1,342 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015, 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 6700100
|
||||||
|
* @summary small instance clone as loads/stores
|
||||||
|
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:CompileCommand=dontinline,TestInstanceCloneAsLoadsStores::m* TestInstanceCloneAsLoadsStores
|
||||||
|
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:CompileCommand=dontinline,TestInstanceCloneAsLoadsStores::m* -XX:+IgnoreUnrecognizedVMOptions -XX:+StressArrayCopyMacroNode TestInstanceCloneAsLoadsStores
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class TestInstanceCloneAsLoadsStores {
|
||||||
|
static class Base implements Cloneable {
|
||||||
|
void initialize(Class c, int i) {
|
||||||
|
for (Field f : c.getDeclaredFields()) {
|
||||||
|
setVal(f, i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (c != Base.class) {
|
||||||
|
initialize(c.getSuperclass(), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Base() {
|
||||||
|
initialize(getClass(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setVal(Field f, int i) {
|
||||||
|
try {
|
||||||
|
if (f.getType() == int.class) {
|
||||||
|
f.setInt(this, i);
|
||||||
|
return;
|
||||||
|
} else if (f.getType() == short.class) {
|
||||||
|
f.setShort(this, (short)i);
|
||||||
|
return;
|
||||||
|
} else if (f.getType() == byte.class) {
|
||||||
|
f.setByte(this, (byte)i);
|
||||||
|
return;
|
||||||
|
} else if (f.getType() == long.class) {
|
||||||
|
f.setLong(this, i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch(IllegalAccessException iae) {
|
||||||
|
throw new RuntimeException("Getting fields failed");
|
||||||
|
}
|
||||||
|
throw new RuntimeException("unexpected field type");
|
||||||
|
}
|
||||||
|
|
||||||
|
int getVal(Field f) {
|
||||||
|
try {
|
||||||
|
if (f.getType() == int.class) {
|
||||||
|
return f.getInt(this);
|
||||||
|
} else if (f.getType() == short.class) {
|
||||||
|
return (int)f.getShort(this);
|
||||||
|
} else if (f.getType() == byte.class) {
|
||||||
|
return (int)f.getByte(this);
|
||||||
|
} else if (f.getType() == long.class) {
|
||||||
|
return (int)f.getLong(this);
|
||||||
|
}
|
||||||
|
} catch(IllegalAccessException iae) {
|
||||||
|
throw new RuntimeException("Setting fields failed");
|
||||||
|
}
|
||||||
|
throw new RuntimeException("unexpected field type");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean fields_equal(Class c, Base o) {
|
||||||
|
for (Field f : c.getDeclaredFields()) {
|
||||||
|
if (getVal(f) != o.getVal(f)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c != Base.class) {
|
||||||
|
return fields_equal(c.getSuperclass(), o);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
return fields_equal(getClass(), (Base)obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
String print_fields(Class c, String s) {
|
||||||
|
for (Field f : c.getDeclaredFields()) {
|
||||||
|
if (s != "") {
|
||||||
|
s += "\n";
|
||||||
|
}
|
||||||
|
s = s + f + " = " + getVal(f);
|
||||||
|
}
|
||||||
|
if (c != Base.class) {
|
||||||
|
return print_fields(c.getSuperclass(), s);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return print_fields(getClass(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
int fields_sum(Class c, int s) {
|
||||||
|
for (Field f : c.getDeclaredFields()) {
|
||||||
|
s += getVal(f);
|
||||||
|
}
|
||||||
|
if (c != Base.class) {
|
||||||
|
return fields_sum(c.getSuperclass(), s);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int sum() {
|
||||||
|
return fields_sum(getClass(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class A extends Base {
|
||||||
|
int i1;
|
||||||
|
int i2;
|
||||||
|
int i3;
|
||||||
|
int i4;
|
||||||
|
int i5;
|
||||||
|
|
||||||
|
public Object clone() throws CloneNotSupportedException {
|
||||||
|
return super.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class B extends A {
|
||||||
|
int i6;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class D extends Base {
|
||||||
|
byte i1;
|
||||||
|
short i2;
|
||||||
|
long i3;
|
||||||
|
int i4;
|
||||||
|
int i5;
|
||||||
|
|
||||||
|
public Object clone() throws CloneNotSupportedException {
|
||||||
|
return super.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class E extends Base {
|
||||||
|
int i1;
|
||||||
|
int i2;
|
||||||
|
int i3;
|
||||||
|
int i4;
|
||||||
|
int i5;
|
||||||
|
int i6;
|
||||||
|
int i7;
|
||||||
|
int i8;
|
||||||
|
int i9;
|
||||||
|
|
||||||
|
public Object clone() throws CloneNotSupportedException {
|
||||||
|
return super.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class F extends Base {
|
||||||
|
public Object clone() throws CloneNotSupportedException {
|
||||||
|
return super.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class G extends Base {
|
||||||
|
int i1;
|
||||||
|
int i2;
|
||||||
|
int i3;
|
||||||
|
|
||||||
|
public Object myclone() throws CloneNotSupportedException {
|
||||||
|
return clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class H extends G {
|
||||||
|
int i4;
|
||||||
|
int i5;
|
||||||
|
|
||||||
|
public Object clone() throws CloneNotSupportedException {
|
||||||
|
return super.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class J extends Base {
|
||||||
|
int i1;
|
||||||
|
int i2;
|
||||||
|
int i3;
|
||||||
|
|
||||||
|
public Object myclone() throws CloneNotSupportedException {
|
||||||
|
return clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class K extends J {
|
||||||
|
int i4;
|
||||||
|
int i5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should be compiled as loads/stores
|
||||||
|
static Object m1(D src) throws CloneNotSupportedException {
|
||||||
|
return src.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should be compiled as adds of src (dest allocation eliminated)
|
||||||
|
static int m2(D src) throws CloneNotSupportedException {
|
||||||
|
D dest = (D)src.clone();
|
||||||
|
return dest.i1 + dest.i2 + ((int)dest.i3) + dest.i4 + dest.i5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should be compiled as arraycopy stub call (object too large)
|
||||||
|
static int m3(E src) throws CloneNotSupportedException {
|
||||||
|
E dest = (E)src.clone();
|
||||||
|
return dest.i1 + dest.i2 + dest.i3 + dest.i4 + dest.i5 +
|
||||||
|
dest.i6 + dest.i7 + dest.i8 + dest.i9;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need profiling on src's type to be able to know number of
|
||||||
|
// fields. Cannot clone as loads/stores if compile doesn't use it.
|
||||||
|
static Object m4(A src) throws CloneNotSupportedException {
|
||||||
|
return src.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same as above but should optimize out dest allocation
|
||||||
|
static int m5(A src) throws CloneNotSupportedException {
|
||||||
|
A dest = (A)src.clone();
|
||||||
|
return dest.i1 + dest.i2 + dest.i3 + dest.i4 + dest.i5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that if we have no fields to clone we do fine
|
||||||
|
static Object m6(F src) throws CloneNotSupportedException {
|
||||||
|
return src.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
// With virtual call to clone: clone inlined from profling which
|
||||||
|
// gives us exact type of src so we can clone it with
|
||||||
|
// loads/stores.
|
||||||
|
static G m7(G src) throws CloneNotSupportedException {
|
||||||
|
return (G)src.myclone();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Virtual call to clone but single target: exact type unknown,
|
||||||
|
// clone intrinsic uses profiling to determine exact type and
|
||||||
|
// clone with loads/stores.
|
||||||
|
static J m8(J src) throws CloneNotSupportedException {
|
||||||
|
return (J)src.myclone();
|
||||||
|
}
|
||||||
|
|
||||||
|
final HashMap<String,Method> tests = new HashMap<>();
|
||||||
|
{
|
||||||
|
for (Method m : this.getClass().getDeclaredMethods()) {
|
||||||
|
if (m.getName().matches("m[0-9]+")) {
|
||||||
|
assert(Modifier.isStatic(m.getModifiers())) : m;
|
||||||
|
tests.put(m.getName(), m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean success = true;
|
||||||
|
|
||||||
|
void doTest(Base src, String name) throws Exception {
|
||||||
|
Method m = tests.get(name);
|
||||||
|
|
||||||
|
for (int i = 0; i < 20000; i++) {
|
||||||
|
boolean failure = false;
|
||||||
|
Base res = null;
|
||||||
|
int s = 0;
|
||||||
|
if (m.getReturnType().isPrimitive()) {
|
||||||
|
s = (int)m.invoke(null, src);
|
||||||
|
failure = (s != src.sum());
|
||||||
|
} else {
|
||||||
|
res = (Base)m.invoke(null, src);
|
||||||
|
failure = !res.equals(src);
|
||||||
|
}
|
||||||
|
if (failure) {
|
||||||
|
System.out.println("Test " + name + " failed");
|
||||||
|
System.out.println("source: ");
|
||||||
|
System.out.println(src);
|
||||||
|
System.out.println("result: ");
|
||||||
|
if (m.getReturnType().isPrimitive()) {
|
||||||
|
System.out.println(s);
|
||||||
|
} else {
|
||||||
|
System.out.println(res);
|
||||||
|
}
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
TestInstanceCloneAsLoadsStores test = new TestInstanceCloneAsLoadsStores();
|
||||||
|
|
||||||
|
A a = new A();
|
||||||
|
B b = new B();
|
||||||
|
D d = new D();
|
||||||
|
E e = new E();
|
||||||
|
F f = new F();
|
||||||
|
G g = new G();
|
||||||
|
H h = new H();
|
||||||
|
J j = new J();
|
||||||
|
K k = new K();
|
||||||
|
|
||||||
|
test.doTest(d, "m1");
|
||||||
|
test.doTest(d, "m2");
|
||||||
|
test.doTest(e, "m3");
|
||||||
|
test.doTest(a, "m4");
|
||||||
|
test.doTest(a, "m5");
|
||||||
|
test.doTest(f, "m6");
|
||||||
|
test.doTest(g, "m7");
|
||||||
|
test.doTest(k, "m8");
|
||||||
|
|
||||||
|
if (!test.success) {
|
||||||
|
throw new RuntimeException("some tests failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,7 +26,7 @@
|
||||||
##
|
##
|
||||||
## @test
|
## @test
|
||||||
## @bug 8011675
|
## @bug 8011675
|
||||||
## @ignore 8031978
|
## @ignore 8029528
|
||||||
## @summary testing of ciReplay with using generated by SA replay.txt
|
## @summary testing of ciReplay with using generated by SA replay.txt
|
||||||
## @author igor.ignatyev@oracle.com
|
## @author igor.ignatyev@oracle.com
|
||||||
## @run shell TestSA.sh
|
## @run shell TestSA.sh
|
||||||
|
@ -69,7 +69,6 @@ fi
|
||||||
|
|
||||||
echo "dumpreplaydata -a > ${replay_data}" | \
|
echo "dumpreplaydata -a > ${replay_data}" | \
|
||||||
${JAVA} ${TESTOPTS} \
|
${JAVA} ${TESTOPTS} \
|
||||||
-cp ${TESTJAVA}${FS}lib${FS}sa-jdi.jar \
|
|
||||||
sun.jvm.hotspot.CLHSDB ${JAVA} ${core_file}
|
sun.jvm.hotspot.CLHSDB ${JAVA} ${core_file}
|
||||||
|
|
||||||
if [ ! -s ${replay_data} ]
|
if [ ! -s ${replay_data} ]
|
||||||
|
|
|
@ -263,10 +263,10 @@ generate_replay() {
|
||||||
dir=`dirname $core_with_dir`
|
dir=`dirname $core_with_dir`
|
||||||
file=`basename $core_with_dir`
|
file=`basename $core_with_dir`
|
||||||
# add <core_path>/core.<pid> core
|
# add <core_path>/core.<pid> core
|
||||||
core_locations="'$core_with_dir' '$file'"
|
core_locations='$core_with_dir' '$file'
|
||||||
if [ -n "${core_with_pid}" ]
|
if [ -n "${core_with_pid}" ]
|
||||||
then
|
then
|
||||||
core_locations="$core_locations '$core_with_pid' '$dir${FS}$core_with_pid'"
|
core_locations=$core_locations '$core_with_pid' '$dir${FS}$core_with_pid'
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,182 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
import com.oracle.java.testlibrary.ExitCode;
|
||||||
|
import com.oracle.java.testlibrary.Platform;
|
||||||
|
import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
|
||||||
|
import common.CodeCacheOptions;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 8015774
|
||||||
|
* @summary Verify SegmentedCodeCache option's processing
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build TestSegmentedCodeCacheOption com.oracle.java.testlibrary.*
|
||||||
|
* @run main TestSegmentedCodeCacheOption
|
||||||
|
*/
|
||||||
|
public class TestSegmentedCodeCacheOption {
|
||||||
|
private static final String INT_MODE = "-Xint";
|
||||||
|
private static final String TIERED_COMPILATION = "TieredCompilation";
|
||||||
|
private static final String SEGMENTED_CODE_CACHE = "SegmentedCodeCache";
|
||||||
|
private static final String USE_SEGMENTED_CODE_CACHE
|
||||||
|
= CommandLineOptionTest.prepareBooleanFlag(SEGMENTED_CODE_CACHE,
|
||||||
|
true);
|
||||||
|
private static final long THRESHOLD_CC_SIZE_VALUE
|
||||||
|
= CodeCacheOptions.mB(240);
|
||||||
|
private static final long BELOW_THRESHOLD_CC_SIZE
|
||||||
|
= THRESHOLD_CC_SIZE_VALUE - CodeCacheOptions.mB(1);
|
||||||
|
private static final String[] UNEXPECTED_MESSAGES = new String[] {
|
||||||
|
".*" + SEGMENTED_CODE_CACHE + ".*"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private static enum TestCase {
|
||||||
|
JVM_STARTUP {
|
||||||
|
@Override
|
||||||
|
public void run() throws Throwable {
|
||||||
|
// There should be no errors when we're trying to enable SCC ...
|
||||||
|
String testCaseWarningMessage = "JVM output should not contain "
|
||||||
|
+ "any warnings related to " + SEGMENTED_CODE_CACHE;
|
||||||
|
String testCaseExitCodeMessage = "JVM should start without any "
|
||||||
|
+ "issues with " + USE_SEGMENTED_CODE_CACHE;
|
||||||
|
|
||||||
|
CommandLineOptionTest.verifySameJVMStartup(
|
||||||
|
/* expectedMessages */ null, UNEXPECTED_MESSAGES,
|
||||||
|
testCaseExitCodeMessage, testCaseWarningMessage,
|
||||||
|
ExitCode.OK, USE_SEGMENTED_CODE_CACHE);
|
||||||
|
// ... and when we're trying to enable it w/o TieredCompilation
|
||||||
|
testCaseExitCodeMessage = "Disabled tiered compilation should "
|
||||||
|
+ "not cause startup failure w/ "
|
||||||
|
+ USE_SEGMENTED_CODE_CACHE;
|
||||||
|
|
||||||
|
CommandLineOptionTest.verifySameJVMStartup(
|
||||||
|
/* expectedMessages */ null, UNEXPECTED_MESSAGES,
|
||||||
|
testCaseExitCodeMessage, testCaseWarningMessage,
|
||||||
|
ExitCode.OK, USE_SEGMENTED_CODE_CACHE,
|
||||||
|
CommandLineOptionTest.prepareBooleanFlag(
|
||||||
|
TIERED_COMPILATION, false));
|
||||||
|
// ... and even w/ Xint.
|
||||||
|
testCaseExitCodeMessage = "It should be possible to use "
|
||||||
|
+ USE_SEGMENTED_CODE_CACHE + " in interpreted mode "
|
||||||
|
+ "without any errors.";
|
||||||
|
|
||||||
|
CommandLineOptionTest.verifyJVMStartup(
|
||||||
|
/* expected messages */ null, UNEXPECTED_MESSAGES,
|
||||||
|
testCaseExitCodeMessage, testCaseWarningMessage,
|
||||||
|
ExitCode.OK, false, INT_MODE, USE_SEGMENTED_CODE_CACHE);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
OPTION_VALUES_GENERIC {
|
||||||
|
@Override
|
||||||
|
public void run() throws Throwable {
|
||||||
|
// SCC is disabled w/o TieredCompilation by default
|
||||||
|
String errorMessage = SEGMENTED_CODE_CACHE
|
||||||
|
+ " should be disabled by default when tiered "
|
||||||
|
+ "compilation is disabled";
|
||||||
|
|
||||||
|
CommandLineOptionTest.verifyOptionValueForSameVM(
|
||||||
|
SEGMENTED_CODE_CACHE, "false", errorMessage,
|
||||||
|
CommandLineOptionTest.prepareBooleanFlag(
|
||||||
|
TIERED_COMPILATION, false));
|
||||||
|
// SCC is disabled by default when ReservedCodeCacheSize is too
|
||||||
|
// small
|
||||||
|
errorMessage = String.format("%s should be disabled bu default "
|
||||||
|
+ "when %s value is too small.", SEGMENTED_CODE_CACHE,
|
||||||
|
BlobType.All.sizeOptionName);
|
||||||
|
|
||||||
|
CommandLineOptionTest.verifyOptionValueForSameVM(
|
||||||
|
SEGMENTED_CODE_CACHE, "false", errorMessage,
|
||||||
|
CommandLineOptionTest.prepareNumericFlag(
|
||||||
|
BlobType.All.sizeOptionName,
|
||||||
|
BELOW_THRESHOLD_CC_SIZE));
|
||||||
|
// SCC could be explicitly enabled w/ Xint
|
||||||
|
errorMessage = String.format("It should be possible to "
|
||||||
|
+ "explicitly enable %s in interpreted mode.",
|
||||||
|
SEGMENTED_CODE_CACHE);
|
||||||
|
|
||||||
|
CommandLineOptionTest.verifyOptionValue(SEGMENTED_CODE_CACHE,
|
||||||
|
"true", errorMessage, false, INT_MODE,
|
||||||
|
USE_SEGMENTED_CODE_CACHE);
|
||||||
|
// SCC could be explicitly enabled w/o TieredCompilation and w/
|
||||||
|
// small ReservedCodeCacheSize value
|
||||||
|
errorMessage = String.format("It should be possible to "
|
||||||
|
+ "explicitly enable %s with small %s and "
|
||||||
|
+ "disabled tiered comp.", SEGMENTED_CODE_CACHE,
|
||||||
|
BlobType.All.sizeOptionName);
|
||||||
|
|
||||||
|
CommandLineOptionTest.verifyOptionValueForSameVM(
|
||||||
|
SEGMENTED_CODE_CACHE, "true", errorMessage,
|
||||||
|
CommandLineOptionTest.prepareBooleanFlag(
|
||||||
|
TIERED_COMPILATION, false),
|
||||||
|
CommandLineOptionTest.prepareNumericFlag(
|
||||||
|
BlobType.All.sizeOptionName,
|
||||||
|
BELOW_THRESHOLD_CC_SIZE),
|
||||||
|
USE_SEGMENTED_CODE_CACHE);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
OPTION_VALUES_SERVER_SPECIFIC {
|
||||||
|
@Override
|
||||||
|
public boolean isApplicable() {
|
||||||
|
return Platform.isServer() && Platform.isTieredSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() throws Throwable {
|
||||||
|
// SCC is enabled by default when TieredCompilation is on and
|
||||||
|
// ReservedCodeCacheSize is large enough
|
||||||
|
String errorMessage = String.format("Large enough %s and "
|
||||||
|
+ "enabled tiered compilation should enable %s "
|
||||||
|
+ "by default.", BlobType.All.sizeOptionName,
|
||||||
|
SEGMENTED_CODE_CACHE);
|
||||||
|
|
||||||
|
CommandLineOptionTest.verifyOptionValueForSameVM(
|
||||||
|
SEGMENTED_CODE_CACHE, "true", errorMessage,
|
||||||
|
CommandLineOptionTest.prepareNumericFlag(
|
||||||
|
BlobType.All.sizeOptionName,
|
||||||
|
THRESHOLD_CC_SIZE_VALUE),
|
||||||
|
CommandLineOptionTest.prepareBooleanFlag(
|
||||||
|
TIERED_COMPILATION, true));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TestCase() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isApplicable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void run() throws Throwable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String args[]) throws Throwable {
|
||||||
|
for (TestCase testCase : TestCase.values()) {
|
||||||
|
if (testCase.isApplicable()) {
|
||||||
|
System.out.println("Running test case: " + testCase.name());
|
||||||
|
testCase.run();
|
||||||
|
} else {
|
||||||
|
System.out.println("Test case skipped: " + testCase.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
package codeheapsize;
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.ExitCode;
|
||||||
|
import com.oracle.java.testlibrary.Platform;
|
||||||
|
import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
|
||||||
|
import common.CodeCacheCLITestCase;
|
||||||
|
import common.CodeCacheOptions;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test case runner aimed to verify that NonNMethodCodeHeapSize smaller than
|
||||||
|
* CodeCacheMinimumUseSpace cause JVM startup failure.
|
||||||
|
*/
|
||||||
|
public class CodeCacheFreeSpaceRunner implements CodeCacheCLITestCase.Runner {
|
||||||
|
private static final String CC_MIN_USE_SPACE = "CodeCacheMinimumUseSpace";
|
||||||
|
private static final String TOO_SMALL_NMETHOD_CH_ERROR
|
||||||
|
= "Invalid NonNMethodCodeHeapSize.*";
|
||||||
|
private static final long MULTIPLIER = Platform.isDebugBuild() ? 3L : 1L;
|
||||||
|
@Override
|
||||||
|
public void run(CodeCacheCLITestCase.Description testCaseDescription,
|
||||||
|
CodeCacheOptions options) throws Throwable {
|
||||||
|
long ccMinUseSpace = ((options.nonNmethods - 1) / MULTIPLIER + 1);
|
||||||
|
|
||||||
|
String exitCodeErrorMessage = String.format("JVM startup should fail "
|
||||||
|
+ "if %s's value lower then %s.",
|
||||||
|
BlobType.NonNMethod.sizeOptionName, CC_MIN_USE_SPACE);
|
||||||
|
String vmOutputErrorMessage = String.format("JVM's output should "
|
||||||
|
+ "contain appropriate error message when %s lower "
|
||||||
|
+ "then %s.", BlobType.NonNMethod.sizeOptionName,
|
||||||
|
CC_MIN_USE_SPACE);
|
||||||
|
|
||||||
|
CommandLineOptionTest.verifySameJVMStartup(
|
||||||
|
new String[]{ TOO_SMALL_NMETHOD_CH_ERROR },
|
||||||
|
/* unexpected messages */ null,
|
||||||
|
exitCodeErrorMessage, vmOutputErrorMessage, ExitCode.FAIL,
|
||||||
|
testCaseDescription.getTestOptions(options,
|
||||||
|
CommandLineOptionTest.prepareNumericFlag(
|
||||||
|
CC_MIN_USE_SPACE, ccMinUseSpace + 1)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
package codeheapsize;
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
|
||||||
|
import common.CodeCacheCLITestCase;
|
||||||
|
import common.CodeCacheOptions;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test case runner aimed to verify that all four options related to code cache
|
||||||
|
* sizing have correct values.
|
||||||
|
*/
|
||||||
|
public class GenericCodeHeapSizeRunner implements CodeCacheCLITestCase.Runner {
|
||||||
|
@Override
|
||||||
|
public void run(CodeCacheCLITestCase.Description testCaseDescription,
|
||||||
|
CodeCacheOptions options) throws Throwable {
|
||||||
|
CodeCacheOptions expectedValues
|
||||||
|
= options.mapOptions(testCaseDescription.involvedCodeHeaps);
|
||||||
|
|
||||||
|
CommandLineOptionTest.verifyOptionValueForSameVM(
|
||||||
|
BlobType.All.sizeOptionName,
|
||||||
|
Long.toString(expectedValues.reserved),
|
||||||
|
String.format("%s should have value %d.",
|
||||||
|
BlobType.All.sizeOptionName, expectedValues.reserved),
|
||||||
|
testCaseDescription.getTestOptions(options));
|
||||||
|
|
||||||
|
CommandLineOptionTest.verifyOptionValueForSameVM(
|
||||||
|
BlobType.NonNMethod.sizeOptionName,
|
||||||
|
Long.toString(expectedValues.nonNmethods),
|
||||||
|
String.format("%s should have value %d.",
|
||||||
|
BlobType.NonNMethod.sizeOptionName,
|
||||||
|
expectedValues.nonNmethods),
|
||||||
|
testCaseDescription.getTestOptions(options));
|
||||||
|
|
||||||
|
CommandLineOptionTest.verifyOptionValueForSameVM(
|
||||||
|
BlobType.MethodNonProfiled.sizeOptionName,
|
||||||
|
Long.toString(expectedValues.nonProfiled),
|
||||||
|
String.format("%s should have value %d.",
|
||||||
|
BlobType.MethodNonProfiled.sizeOptionName,
|
||||||
|
expectedValues.nonProfiled),
|
||||||
|
testCaseDescription.getTestOptions(options));
|
||||||
|
|
||||||
|
CommandLineOptionTest.verifyOptionValueForSameVM(
|
||||||
|
BlobType.MethodProfiled.sizeOptionName,
|
||||||
|
Long.toString(expectedValues.profiled),
|
||||||
|
String.format("%s should have value %d.",
|
||||||
|
BlobType.MethodProfiled.sizeOptionName,
|
||||||
|
expectedValues.profiled),
|
||||||
|
testCaseDescription.getTestOptions(options));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
package codeheapsize;
|
||||||
|
|
||||||
|
import common.CodeCacheCLITestCase;
|
||||||
|
import common.CodeCacheOptions;
|
||||||
|
import com.oracle.java.testlibrary.ExitCode;
|
||||||
|
import com.oracle.java.testlibrary.Utils;
|
||||||
|
import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test case runner aimed to verify option's consistency.
|
||||||
|
*/
|
||||||
|
public class JVMStartupRunner implements CodeCacheCLITestCase.Runner {
|
||||||
|
private static final String INCONSISTENT_CH_SIZES_ERROR
|
||||||
|
= "Invalid code heap sizes.*";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(CodeCacheCLITestCase.Description testCaseDescription,
|
||||||
|
CodeCacheOptions options) throws Throwable {
|
||||||
|
// Everything should be fine when
|
||||||
|
// sum(all code heap sizes) == reserved CC size
|
||||||
|
CommandLineOptionTest.verifySameJVMStartup(/* expected messages */ null,
|
||||||
|
new String[]{ INCONSISTENT_CH_SIZES_ERROR },
|
||||||
|
"JVM startup should not fail with consistent code heap sizes",
|
||||||
|
"JVM output should not contain warning about inconsistent code "
|
||||||
|
+ "heap sizes", ExitCode.OK, options.prepareOptions());
|
||||||
|
|
||||||
|
verifySingleInconsistentValue(options);
|
||||||
|
verifyAllInconsistentValues(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that if at least one of three options will have value, such
|
||||||
|
* that sum of all three values will be inconsistent, then JVM startup will
|
||||||
|
* fail.
|
||||||
|
*/
|
||||||
|
private static void verifySingleInconsistentValue(CodeCacheOptions options)
|
||||||
|
throws Throwable {
|
||||||
|
verifyHeapSizesSum(options.reserved,
|
||||||
|
scaleCodeHeapSize(options.profiled), options.nonProfiled,
|
||||||
|
options.nonNmethods);
|
||||||
|
verifyHeapSizesSum(options.reserved, options.profiled,
|
||||||
|
scaleCodeHeapSize(options.nonProfiled), options.nonNmethods);
|
||||||
|
verifyHeapSizesSum(options.reserved, options.profiled,
|
||||||
|
options.nonProfiled, scaleCodeHeapSize(options.nonNmethods));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that if all three options will have values such that their sum
|
||||||
|
* is inconsistent with ReservedCodeCacheSize value, then JVM startup will
|
||||||
|
* fail.
|
||||||
|
*/
|
||||||
|
private static void verifyAllInconsistentValues(CodeCacheOptions options)
|
||||||
|
throws Throwable {
|
||||||
|
long profiled = options.profiled;
|
||||||
|
long nonProfiled = options.nonProfiled;
|
||||||
|
long nonNMethods = options.nonNmethods;
|
||||||
|
|
||||||
|
while (options.reserved == profiled + nonProfiled + nonNMethods) {
|
||||||
|
profiled = scaleCodeHeapSize(profiled);
|
||||||
|
nonProfiled = scaleCodeHeapSize(nonProfiled);
|
||||||
|
nonNMethods = scaleCodeHeapSize(nonNMethods);
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyHeapSizesSum(options.reserved, profiled, nonProfiled,
|
||||||
|
nonNMethods);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void verifyHeapSizesSum(long reserved, long profiled,
|
||||||
|
long nonProfiled, long nonNmethods) throws Throwable {
|
||||||
|
// JVM startup expected to fail when
|
||||||
|
// sum(all code heap sizes) != reserved CC size
|
||||||
|
CommandLineOptionTest.verifySameJVMStartup(
|
||||||
|
new String[]{ INCONSISTENT_CH_SIZES_ERROR },
|
||||||
|
/* unexpected messages */ null,
|
||||||
|
"JVM startup should fail with inconsistent code heap size.",
|
||||||
|
"JVM output should contain appropriate error message of code "
|
||||||
|
+ "heap sizes are inconsistent",
|
||||||
|
ExitCode.FAIL,
|
||||||
|
CommandLineOptionTest.prepareBooleanFlag(
|
||||||
|
CodeCacheOptions.SEGMENTED_CODE_CACHE, true),
|
||||||
|
CommandLineOptionTest.prepareNumericFlag(
|
||||||
|
BlobType.All.sizeOptionName, reserved),
|
||||||
|
CommandLineOptionTest.prepareNumericFlag(
|
||||||
|
BlobType.MethodProfiled.sizeOptionName, profiled),
|
||||||
|
CommandLineOptionTest.prepareNumericFlag(
|
||||||
|
BlobType.MethodNonProfiled.sizeOptionName, nonProfiled),
|
||||||
|
CommandLineOptionTest.prepareNumericFlag(
|
||||||
|
BlobType.NonNMethod.sizeOptionName, nonNmethods));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code unscaledSize} value scaled by a random factor from
|
||||||
|
* range (1, 2). If {@code unscaledSize} is not 0, then this
|
||||||
|
* method will return value that won't be equal to {@code unscaledSize}.
|
||||||
|
*
|
||||||
|
* @param unscaledSize The value to be scaled.
|
||||||
|
* @return {@code unscaledSize} value scaled by a factor from range (1, 2).
|
||||||
|
*/
|
||||||
|
private static long scaleCodeHeapSize(long unscaledSize) {
|
||||||
|
Random random = Utils.getRandomInstance();
|
||||||
|
|
||||||
|
long scaledSize = unscaledSize;
|
||||||
|
while (scaledSize == unscaledSize && unscaledSize != 0) {
|
||||||
|
float scale = 1.0f + random.nextFloat();
|
||||||
|
scaledSize = (long) Math.ceil(scale * unscaledSize);
|
||||||
|
}
|
||||||
|
return scaledSize;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
package codeheapsize;
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Platform;
|
||||||
|
import common.CodeCacheCLITestBase;
|
||||||
|
import common.CodeCacheCLITestCase;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 8015774
|
||||||
|
* @summary Verify processing of options related to code heaps sizing.
|
||||||
|
* @library /testlibrary .. /../../test/lib
|
||||||
|
* @build TestCodeHeapSizeOptions com.oracle.java.testlibrary.* codeheapsize.*
|
||||||
|
* common.*
|
||||||
|
* @run main/timeout=240 codeheapsize.TestCodeHeapSizeOptions
|
||||||
|
*/
|
||||||
|
public class TestCodeHeapSizeOptions extends CodeCacheCLITestBase {
|
||||||
|
private static final CodeCacheCLITestCase JVM_STARTUP
|
||||||
|
= new CodeCacheCLITestCase(new CodeCacheCLITestCase.Description(
|
||||||
|
options -> options.segmented,
|
||||||
|
EnumSet.noneOf(BlobType.class)),
|
||||||
|
new JVMStartupRunner());
|
||||||
|
|
||||||
|
private static final CodeCacheCLITestCase CODE_CACHE_FREE_SPACE
|
||||||
|
= new CodeCacheCLITestCase(new CodeCacheCLITestCase.Description(
|
||||||
|
options -> options.segmented
|
||||||
|
&& Platform.isDebugBuild(),
|
||||||
|
EnumSet.noneOf(BlobType.class)),
|
||||||
|
new CodeCacheFreeSpaceRunner());
|
||||||
|
|
||||||
|
private static final GenericCodeHeapSizeRunner GENERIC_RUNNER
|
||||||
|
= new GenericCodeHeapSizeRunner();
|
||||||
|
|
||||||
|
private TestCodeHeapSizeOptions() {
|
||||||
|
super(CodeCacheCLITestBase.OPTIONS_SET,
|
||||||
|
new CodeCacheCLITestCase(CodeCacheCLITestCase
|
||||||
|
.CommonDescriptions.INT_MODE.description,
|
||||||
|
GENERIC_RUNNER),
|
||||||
|
new CodeCacheCLITestCase(CodeCacheCLITestCase
|
||||||
|
.CommonDescriptions.NON_TIERED.description,
|
||||||
|
GENERIC_RUNNER),
|
||||||
|
new CodeCacheCLITestCase(CodeCacheCLITestCase
|
||||||
|
.CommonDescriptions.TIERED_LEVEL_0.description,
|
||||||
|
GENERIC_RUNNER),
|
||||||
|
new CodeCacheCLITestCase(CodeCacheCLITestCase
|
||||||
|
.CommonDescriptions.TIERED_LEVEL_1.description,
|
||||||
|
GENERIC_RUNNER),
|
||||||
|
new CodeCacheCLITestCase(CodeCacheCLITestCase
|
||||||
|
.CommonDescriptions.TIERED_LEVEL_4.description,
|
||||||
|
GENERIC_RUNNER),
|
||||||
|
JVM_STARTUP,
|
||||||
|
CODE_CACHE_FREE_SPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String args[]) throws Throwable {
|
||||||
|
new TestCodeHeapSizeOptions().runTestCases();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
package common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base for code cache related command line options tests.
|
||||||
|
*/
|
||||||
|
public class CodeCacheCLITestBase {
|
||||||
|
public static final CodeCacheOptions[] OPTIONS_SET
|
||||||
|
= new CodeCacheOptions[] {
|
||||||
|
new CodeCacheOptions(CodeCacheOptions.mB(60),
|
||||||
|
CodeCacheOptions.mB(20), CodeCacheOptions.mB(20),
|
||||||
|
CodeCacheOptions.mB(20)),
|
||||||
|
new CodeCacheOptions(CodeCacheOptions.mB(200),
|
||||||
|
CodeCacheOptions.mB(75), CodeCacheOptions.mB(75),
|
||||||
|
CodeCacheOptions.mB(50)),
|
||||||
|
new CodeCacheOptions(CodeCacheOptions.mB(300),
|
||||||
|
CodeCacheOptions.mB(100), CodeCacheOptions.mB(100),
|
||||||
|
CodeCacheOptions.mB(100)),
|
||||||
|
new CodeCacheOptions(CodeCacheOptions.mB(60)),
|
||||||
|
new CodeCacheOptions(CodeCacheOptions.mB(200)),
|
||||||
|
new CodeCacheOptions(CodeCacheOptions.mB(300))
|
||||||
|
};
|
||||||
|
|
||||||
|
private final CodeCacheCLITestCase[] testCases;
|
||||||
|
private final CodeCacheOptions[] options;
|
||||||
|
|
||||||
|
public CodeCacheCLITestBase(CodeCacheOptions[] options,
|
||||||
|
CodeCacheCLITestCase... testCases) {
|
||||||
|
this.testCases = testCases;
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runTestCases() throws Throwable {
|
||||||
|
for (CodeCacheCLITestCase testCase : testCases) {
|
||||||
|
for (CodeCacheOptions opts : options) {
|
||||||
|
testCase.run(opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,165 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
package common;
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Platform;
|
||||||
|
import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Code cache related command line option test case consisting of description
|
||||||
|
* of code heaps used during test case run and additional options that should
|
||||||
|
* be passed to JVM and runner aimed to perform actual testing based on the
|
||||||
|
* description.
|
||||||
|
*/
|
||||||
|
public class CodeCacheCLITestCase {
|
||||||
|
private static final Function<CodeCacheOptions, Boolean> ONLY_SEGMENTED
|
||||||
|
= options -> options.segmented;
|
||||||
|
private static final Function<CodeCacheOptions, Boolean> SEGMENTED_SERVER
|
||||||
|
= ONLY_SEGMENTED.andThen(isSegmented -> isSegmented
|
||||||
|
&& Platform.isServer() && Platform.isTieredSupported());
|
||||||
|
private static final String USE_INT_MODE = "-Xint";
|
||||||
|
private static final String SEGMENTED_CODE_CACHE = "SegmentedCodeCache";
|
||||||
|
private static final String TIERED_COMPILATION = "TieredCompilation";
|
||||||
|
private static final String TIERED_STOP_AT = "TieredStopAtLevel";
|
||||||
|
|
||||||
|
private final Description description;
|
||||||
|
private final Runner runner;
|
||||||
|
|
||||||
|
public CodeCacheCLITestCase(Description description, Runner runner) {
|
||||||
|
this.description = description;
|
||||||
|
this.runner = runner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void run(CodeCacheOptions options) throws Throwable {
|
||||||
|
if (description.isApplicable(options)) {
|
||||||
|
runner.run(description, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum CommonDescriptions {
|
||||||
|
/**
|
||||||
|
* Verifies that in interpreted mode PrintCodeCache output contains
|
||||||
|
* only NonNMethod code heap.
|
||||||
|
*/
|
||||||
|
INT_MODE(ONLY_SEGMENTED, EnumSet.of(BlobType.NonNMethod), USE_INT_MODE),
|
||||||
|
/**
|
||||||
|
* Verifies that with disabled SegmentedCodeCache PrintCodeCache output
|
||||||
|
* contains only CodeCache's entry.
|
||||||
|
*/
|
||||||
|
NON_SEGMENTED(options -> !options.segmented, EnumSet.of(BlobType.All),
|
||||||
|
CommandLineOptionTest.prepareBooleanFlag(SEGMENTED_CODE_CACHE,
|
||||||
|
false)),
|
||||||
|
/**
|
||||||
|
* Verifies that with disabled tiered compilation and enabled segmented
|
||||||
|
* code cache PrintCodeCache output does not contain information about
|
||||||
|
* profiled-nmethods heap and non-segmented CodeCache.
|
||||||
|
*/
|
||||||
|
NON_TIERED(ONLY_SEGMENTED,
|
||||||
|
EnumSet.of(BlobType.NonNMethod, BlobType.MethodNonProfiled),
|
||||||
|
CommandLineOptionTest.prepareBooleanFlag(TIERED_COMPILATION,
|
||||||
|
false)),
|
||||||
|
/**
|
||||||
|
* Verifies that with TieredStopAtLevel=0 PrintCodeCache output will
|
||||||
|
* contain information about non-nmethods and non-profiled nmethods
|
||||||
|
* heaps only.
|
||||||
|
*/
|
||||||
|
TIERED_LEVEL_0(SEGMENTED_SERVER,
|
||||||
|
EnumSet.of(BlobType.NonNMethod, BlobType.MethodNonProfiled),
|
||||||
|
CommandLineOptionTest.prepareBooleanFlag(TIERED_COMPILATION,
|
||||||
|
true),
|
||||||
|
CommandLineOptionTest.prepareNumericFlag(TIERED_STOP_AT, 0)),
|
||||||
|
/**
|
||||||
|
* Verifies that with TieredStopAtLevel=1 PrintCodeCache output will
|
||||||
|
* contain information about non-nmethods and non-profiled nmethods
|
||||||
|
* heaps only.
|
||||||
|
*/
|
||||||
|
TIERED_LEVEL_1(SEGMENTED_SERVER,
|
||||||
|
EnumSet.of(BlobType.NonNMethod, BlobType.MethodNonProfiled),
|
||||||
|
CommandLineOptionTest.prepareBooleanFlag(TIERED_COMPILATION,
|
||||||
|
true),
|
||||||
|
CommandLineOptionTest.prepareNumericFlag(TIERED_STOP_AT, 1)),
|
||||||
|
/**
|
||||||
|
* Verifies that with TieredStopAtLevel=4 PrintCodeCache output will
|
||||||
|
* contain information about all three code heaps.
|
||||||
|
*/
|
||||||
|
TIERED_LEVEL_4(SEGMENTED_SERVER,
|
||||||
|
EnumSet.complementOf(EnumSet.of(BlobType.All)),
|
||||||
|
CommandLineOptionTest.prepareBooleanFlag(TIERED_COMPILATION,
|
||||||
|
true),
|
||||||
|
CommandLineOptionTest.prepareNumericFlag(TIERED_STOP_AT, 4));
|
||||||
|
|
||||||
|
CommonDescriptions(Function<CodeCacheOptions, Boolean> predicate,
|
||||||
|
EnumSet<BlobType> involvedCodeHeaps,
|
||||||
|
String... additionalOptions) {
|
||||||
|
this.description = new Description(predicate,
|
||||||
|
involvedCodeHeaps, additionalOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public final Description description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Description {
|
||||||
|
public final EnumSet<BlobType> involvedCodeHeaps;
|
||||||
|
private final String[] testCaseSpecificOptions;
|
||||||
|
private final Function<CodeCacheOptions, Boolean> predicate;
|
||||||
|
|
||||||
|
public Description(Function<CodeCacheOptions, Boolean> predicate,
|
||||||
|
EnumSet<BlobType> involvedCodeHeaps,
|
||||||
|
String... testCaseSpecificOptions) {
|
||||||
|
this.involvedCodeHeaps = involvedCodeHeaps;
|
||||||
|
this.testCaseSpecificOptions = testCaseSpecificOptions;
|
||||||
|
this.predicate = predicate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isApplicable(CodeCacheOptions options) {
|
||||||
|
return predicate.apply(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodeCacheOptions expectedValues(CodeCacheOptions options) {
|
||||||
|
return options.mapOptions(involvedCodeHeaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getTestOptions(CodeCacheOptions codeCacheOptions,
|
||||||
|
String... additionalOptions) {
|
||||||
|
List<String> options = new LinkedList<>();
|
||||||
|
Collections.addAll(options, testCaseSpecificOptions);
|
||||||
|
Collections.addAll(options, additionalOptions);
|
||||||
|
return codeCacheOptions.prepareOptions(
|
||||||
|
options.toArray(new String[options.size()]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static interface Runner {
|
||||||
|
public void run(Description testCaseDescription,
|
||||||
|
CodeCacheOptions options) throws Throwable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
package common;
|
||||||
|
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class CodeCacheInfoFormatter {
|
||||||
|
private static final String DEFAULT_SIZE_FORMAT = "[0-9]+Kb";
|
||||||
|
private BlobType heap = null;
|
||||||
|
private String size = DEFAULT_SIZE_FORMAT;
|
||||||
|
private String used = DEFAULT_SIZE_FORMAT;
|
||||||
|
private String maxUsed = DEFAULT_SIZE_FORMAT;
|
||||||
|
private String free = DEFAULT_SIZE_FORMAT;
|
||||||
|
|
||||||
|
public static CodeCacheInfoFormatter forHeap(BlobType heap) {
|
||||||
|
return new CodeCacheInfoFormatter(heap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String[] forHeaps(BlobType... heaps) {
|
||||||
|
return Arrays.stream(heaps)
|
||||||
|
.map(CodeCacheInfoFormatter::forHeap)
|
||||||
|
.map(CodeCacheInfoFormatter::getInfoString)
|
||||||
|
.toArray(String[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatSize(long suffix) {
|
||||||
|
return String.format("%dKb", suffix / 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CodeCacheInfoFormatter(BlobType heap) {
|
||||||
|
this.heap = heap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodeCacheInfoFormatter withSize(long size) {
|
||||||
|
this.size = CodeCacheInfoFormatter.formatSize(size);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodeCacheInfoFormatter withUsed(long used) {
|
||||||
|
this.used = CodeCacheInfoFormatter.formatSize(used);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodeCacheInfoFormatter withMaxUsed(long maxUsed) {
|
||||||
|
this.maxUsed = CodeCacheInfoFormatter.formatSize(maxUsed);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodeCacheInfoFormatter withFree(long free) {
|
||||||
|
this.free = CodeCacheInfoFormatter.formatSize(free);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInfoString() {
|
||||||
|
return String.format("%s: size=%s used=%s max_used=%s free=%s",
|
||||||
|
heap.beanName, size, used, maxUsed, free);
|
||||||
|
}
|
||||||
|
}
|
129
hotspot/test/compiler/codecache/cli/common/CodeCacheOptions.java
Normal file
129
hotspot/test/compiler/codecache/cli/common/CodeCacheOptions.java
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
package common;
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CodeCacheOptions {
|
||||||
|
public static final String SEGMENTED_CODE_CACHE = "SegmentedCodeCache";
|
||||||
|
|
||||||
|
private static final EnumSet<BlobType> NON_SEGMENTED_HEAPS
|
||||||
|
= EnumSet.of(BlobType.All);
|
||||||
|
private static final EnumSet<BlobType> ALL_SEGMENTED_HEAPS
|
||||||
|
= EnumSet.complementOf(NON_SEGMENTED_HEAPS);
|
||||||
|
private static final EnumSet<BlobType> SEGMENTED_HEAPS_WO_PROFILED
|
||||||
|
= EnumSet.of(BlobType.NonNMethod, BlobType.MethodNonProfiled);
|
||||||
|
private static final EnumSet<BlobType> ONLY_NON_METHODS_HEAP
|
||||||
|
= EnumSet.of(BlobType.NonNMethod);
|
||||||
|
|
||||||
|
public final long reserved;
|
||||||
|
public final long nonNmethods;
|
||||||
|
public final long nonProfiled;
|
||||||
|
public final long profiled;
|
||||||
|
public final boolean segmented;
|
||||||
|
|
||||||
|
public static long mB(long val) {
|
||||||
|
return CodeCacheOptions.kB(val) * 1024L;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long kB(long val) {
|
||||||
|
return val * 1024L;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodeCacheOptions(long reserved) {
|
||||||
|
this.reserved = reserved;
|
||||||
|
this.nonNmethods = 0;
|
||||||
|
this.nonProfiled = 0;
|
||||||
|
this.profiled = 0;
|
||||||
|
this.segmented = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodeCacheOptions(long reserved, long nonNmethods, long nonProfiled,
|
||||||
|
long profiled) {
|
||||||
|
this.reserved = reserved;
|
||||||
|
this.nonNmethods = nonNmethods;
|
||||||
|
this.nonProfiled = nonProfiled;
|
||||||
|
this.profiled = profiled;
|
||||||
|
this.segmented = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long sizeForHeap(BlobType heap) {
|
||||||
|
switch (heap) {
|
||||||
|
case All:
|
||||||
|
return this.reserved;
|
||||||
|
case NonNMethod:
|
||||||
|
return this.nonNmethods;
|
||||||
|
case MethodNonProfiled:
|
||||||
|
return this.nonProfiled;
|
||||||
|
case MethodProfiled:
|
||||||
|
return this.profiled;
|
||||||
|
default:
|
||||||
|
throw new Error("Unknown heap: " + heap.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] prepareOptions(String... additionalOptions) {
|
||||||
|
List<String> options = new ArrayList<>();
|
||||||
|
Collections.addAll(options, additionalOptions);
|
||||||
|
Collections.addAll(options,
|
||||||
|
CommandLineOptionTest.prepareBooleanFlag(
|
||||||
|
SEGMENTED_CODE_CACHE, segmented),
|
||||||
|
CommandLineOptionTest.prepareNumericFlag(
|
||||||
|
BlobType.All.sizeOptionName, reserved));
|
||||||
|
|
||||||
|
if (segmented) {
|
||||||
|
Collections.addAll(options,
|
||||||
|
CommandLineOptionTest.prepareNumericFlag(
|
||||||
|
BlobType.NonNMethod.sizeOptionName, nonNmethods),
|
||||||
|
CommandLineOptionTest.prepareNumericFlag(
|
||||||
|
BlobType.MethodNonProfiled.sizeOptionName,
|
||||||
|
nonProfiled),
|
||||||
|
CommandLineOptionTest.prepareNumericFlag(
|
||||||
|
BlobType.MethodProfiled.sizeOptionName, profiled));
|
||||||
|
}
|
||||||
|
return options.toArray(new String[options.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodeCacheOptions mapOptions(EnumSet<BlobType> involvedCodeHeaps) {
|
||||||
|
if (involvedCodeHeaps.isEmpty()
|
||||||
|
|| involvedCodeHeaps.equals(NON_SEGMENTED_HEAPS)
|
||||||
|
|| involvedCodeHeaps.equals(ALL_SEGMENTED_HEAPS)) {
|
||||||
|
return this;
|
||||||
|
} else if (involvedCodeHeaps.equals(SEGMENTED_HEAPS_WO_PROFILED)) {
|
||||||
|
return new CodeCacheOptions(reserved, nonNmethods,
|
||||||
|
profiled + nonProfiled, 0L);
|
||||||
|
} else if (involvedCodeHeaps.equals(ONLY_NON_METHODS_HEAP)) {
|
||||||
|
return new CodeCacheOptions(reserved, nonNmethods + profiled
|
||||||
|
+ nonProfiled, 0L, 0L);
|
||||||
|
} else {
|
||||||
|
throw new Error("Test bug: unexpected set of code heaps involved "
|
||||||
|
+ "into test.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
package printcodecache;
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.ExitCode;
|
||||||
|
import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
|
||||||
|
import common.CodeCacheCLITestCase;
|
||||||
|
import common.CodeCacheInfoFormatter;
|
||||||
|
import common.CodeCacheOptions;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runner implementation aimed to verify PrintCodeCache output.
|
||||||
|
*/
|
||||||
|
public class PrintCodeCacheRunner implements CodeCacheCLITestCase.Runner {
|
||||||
|
private final boolean printCodeCache;
|
||||||
|
|
||||||
|
public PrintCodeCacheRunner(boolean printCodeCache) {
|
||||||
|
this.printCodeCache = printCodeCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrintCodeCacheRunner() {
|
||||||
|
this(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(CodeCacheCLITestCase.Description testCaseDescription,
|
||||||
|
CodeCacheOptions options) throws Throwable {
|
||||||
|
CodeCacheOptions expectedValues
|
||||||
|
= testCaseDescription.expectedValues(options);
|
||||||
|
|
||||||
|
String[] expectedMessages
|
||||||
|
= testCaseDescription.involvedCodeHeaps.stream()
|
||||||
|
.map(heap -> CodeCacheInfoFormatter.forHeap(heap)
|
||||||
|
.withSize(expectedValues.sizeForHeap(heap)))
|
||||||
|
.map(CodeCacheInfoFormatter::getInfoString)
|
||||||
|
.toArray(String[]::new);
|
||||||
|
|
||||||
|
EnumSet<BlobType> unexpectedHeapsSet
|
||||||
|
= EnumSet.complementOf(testCaseDescription.involvedCodeHeaps);
|
||||||
|
|
||||||
|
String[] unexpectedMessages = CodeCacheInfoFormatter.forHeaps(
|
||||||
|
unexpectedHeapsSet.toArray(
|
||||||
|
new BlobType[unexpectedHeapsSet.size()]));
|
||||||
|
|
||||||
|
String description = String.format("JVM output should contain entries "
|
||||||
|
+ "for following code heaps: [%s] and should not contain "
|
||||||
|
+ "entries for following code heaps: [%s].",
|
||||||
|
testCaseDescription.involvedCodeHeaps.stream()
|
||||||
|
.map(BlobType::name)
|
||||||
|
.collect(Collectors.joining(", ")),
|
||||||
|
unexpectedHeapsSet.stream()
|
||||||
|
.map(BlobType::name)
|
||||||
|
.collect(Collectors.joining(", ")));
|
||||||
|
|
||||||
|
CommandLineOptionTest.verifySameJVMStartup(expectedMessages,
|
||||||
|
unexpectedMessages, "JVM startup failure is not expected, "
|
||||||
|
+ "since all options have allowed values", description,
|
||||||
|
ExitCode.OK,
|
||||||
|
testCaseDescription.getTestOptions(options,
|
||||||
|
CommandLineOptionTest.prepareBooleanFlag(
|
||||||
|
"PrintCodeCache", printCodeCache)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
package printcodecache;
|
||||||
|
|
||||||
|
import common.CodeCacheCLITestBase;
|
||||||
|
import common.CodeCacheCLITestCase;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 8015774
|
||||||
|
* @summary Verify that PrintCodeCache option print correct information.
|
||||||
|
* @library /testlibrary .. /../../test/lib
|
||||||
|
* @build TestPrintCodeCacheOption com.oracle.java.testlibrary.*
|
||||||
|
* printcodecache.* common.*
|
||||||
|
* @run main/timeout=240 printcodecache.TestPrintCodeCacheOption
|
||||||
|
*/
|
||||||
|
public class TestPrintCodeCacheOption extends CodeCacheCLITestBase {
|
||||||
|
private static final CodeCacheCLITestCase DISABLED_PRINT_CODE_CACHE
|
||||||
|
= new CodeCacheCLITestCase(new CodeCacheCLITestCase.Description(
|
||||||
|
options -> true, EnumSet.noneOf(BlobType.class)),
|
||||||
|
new PrintCodeCacheRunner(false));
|
||||||
|
|
||||||
|
private static final CodeCacheCLITestCase.Runner DEFAULT_RUNNER
|
||||||
|
= new PrintCodeCacheRunner();
|
||||||
|
|
||||||
|
private TestPrintCodeCacheOption() {
|
||||||
|
super(CodeCacheCLITestBase.OPTIONS_SET,
|
||||||
|
new CodeCacheCLITestCase(CodeCacheCLITestCase
|
||||||
|
.CommonDescriptions.INT_MODE.description,
|
||||||
|
DEFAULT_RUNNER),
|
||||||
|
new CodeCacheCLITestCase(CodeCacheCLITestCase
|
||||||
|
.CommonDescriptions.NON_SEGMENTED.description,
|
||||||
|
DEFAULT_RUNNER),
|
||||||
|
new CodeCacheCLITestCase(CodeCacheCLITestCase
|
||||||
|
.CommonDescriptions.NON_TIERED.description,
|
||||||
|
DEFAULT_RUNNER),
|
||||||
|
new CodeCacheCLITestCase(CodeCacheCLITestCase
|
||||||
|
.CommonDescriptions.TIERED_LEVEL_0.description,
|
||||||
|
DEFAULT_RUNNER),
|
||||||
|
new CodeCacheCLITestCase(CodeCacheCLITestCase
|
||||||
|
.CommonDescriptions.TIERED_LEVEL_1.description,
|
||||||
|
DEFAULT_RUNNER),
|
||||||
|
new CodeCacheCLITestCase(CodeCacheCLITestCase
|
||||||
|
.CommonDescriptions.TIERED_LEVEL_4.description,
|
||||||
|
DEFAULT_RUNNER),
|
||||||
|
DISABLED_PRINT_CODE_CACHE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String args[]) throws Throwable {
|
||||||
|
new TestPrintCodeCacheOption().runTestCases();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,307 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import com.oracle.java.testlibrary.JDKToolFinder;
|
||||||
|
import com.oracle.java.testlibrary.OutputAnalyzer;
|
||||||
|
import com.oracle.java.testlibrary.Utils;
|
||||||
|
import com.oracle.java.testlibrary.dtrace.DtraceResultsAnalyzer;
|
||||||
|
import com.oracle.java.testlibrary.dtrace.DtraceRunner;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Executable;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test SegmentedCodeCacheDtraceTest
|
||||||
|
* @bug 8015774
|
||||||
|
* @requires os.family=="solaris"
|
||||||
|
* @library /testlibrary /compiler/testlibrary /../../test/lib
|
||||||
|
* @build SegmentedCodeCacheDtraceTestWorker
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+TieredCompilation
|
||||||
|
* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
|
* SegmentedCodeCacheDtraceTest
|
||||||
|
* @summary testing of dtrace for segmented code cache
|
||||||
|
*/
|
||||||
|
public class SegmentedCodeCacheDtraceTest {
|
||||||
|
|
||||||
|
private static final String WORKER_CLASS_NAME
|
||||||
|
= SegmentedCodeCacheDtraceTestWorker.class.getName();
|
||||||
|
private static final String JAVA_OPTS = " -XX:+DTraceMethodProbes "
|
||||||
|
+ "-Xbootclasspath/a:" + System.getProperty("test.classes") + " "
|
||||||
|
+ "-XX:+UnlockDiagnosticVMOptions "
|
||||||
|
+ "-XX:+WhiteBoxAPI -XX:+SegmentedCodeCache "
|
||||||
|
+ "-XX:CompileCommand=compileonly,"
|
||||||
|
+ WORKER_CLASS_NAME + "::* "
|
||||||
|
+ " -classpath " + System.getProperty("test.class.path") + " "
|
||||||
|
+ String.join(" ", Utils.getTestJavaOpts());
|
||||||
|
private static final String DTRACE_SCRIPT
|
||||||
|
= "SegmentedCodeCacheDtraceTestScript.d";
|
||||||
|
private static final List<Executable> MLIST =
|
||||||
|
SegmentedCodeCacheDtraceTestWorker.TESTED_METHODS_LIST;
|
||||||
|
private static final int WORKER_METHODS_COUNT = MLIST.size();
|
||||||
|
|
||||||
|
private void runTest(TestCombination tc) {
|
||||||
|
String params = MLIST.stream()
|
||||||
|
.map(Executable::getName)
|
||||||
|
.map(x -> tc.data.get(x).compileLevel + " " + tc.data.get(x).isInlined)
|
||||||
|
.collect(Collectors.joining(" "));
|
||||||
|
DtraceRunner runner = new DtraceRunner();
|
||||||
|
runner.runDtrace(JDKToolFinder.getTestJDKTool("java"), JAVA_OPTS,
|
||||||
|
WORKER_CLASS_NAME, params, Paths.get(System.getProperty("test.src"),
|
||||||
|
DTRACE_SCRIPT).toString(),
|
||||||
|
DtraceRunner.PERMIT_DESTRUCTIVE_ACTIONS_DTRACE_OPTION,
|
||||||
|
new SegmentedCodeCacheDtraceResultsAnalyzer());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TestCombination generateUniqueCombination(
|
||||||
|
int[] availableLevels, Set<TestCombination> combinations) {
|
||||||
|
int len = availableLevels.length;
|
||||||
|
/* first, check if we're out of combinations. */
|
||||||
|
int maxCombinationsCount
|
||||||
|
= (1 << WORKER_METHODS_COUNT)
|
||||||
|
* (int) Math.pow(len, WORKER_METHODS_COUNT);
|
||||||
|
if (combinations.size() == maxCombinationsCount) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Random r = Utils.getRandomInstance();
|
||||||
|
while (combinations.size() < maxCombinationsCount) {
|
||||||
|
int levels[] = new int[WORKER_METHODS_COUNT];
|
||||||
|
boolean inlines[] = new boolean[WORKER_METHODS_COUNT];
|
||||||
|
for (int i = 0; i < WORKER_METHODS_COUNT; i++) {
|
||||||
|
levels[i] = availableLevels[r.nextInt(len)];
|
||||||
|
inlines[i] = r.nextBoolean();
|
||||||
|
}
|
||||||
|
TestCombination tc = new TestCombination(levels, inlines);
|
||||||
|
if (combinations.add(tc)) {
|
||||||
|
return tc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String args[]) {
|
||||||
|
int iterations
|
||||||
|
= Integer.getInteger("com.oracle.java.testlibrary.iterations", 1);
|
||||||
|
if (!DtraceRunner.dtraceAvailable()) {
|
||||||
|
System.out.println("INFO: There is no dtrace avaiable. Skipping.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int[] availableLevels = CompilerUtils.getAvailableCompilationLevels();
|
||||||
|
// adding one more entry(zero) for interpeter
|
||||||
|
availableLevels
|
||||||
|
= Arrays.copyOf(availableLevels, availableLevels.length + 1);
|
||||||
|
Set<TestCombination> combinations = new HashSet<>();
|
||||||
|
for (int i = 0; i < iterations; i++) {
|
||||||
|
TestCombination tc
|
||||||
|
= generateUniqueCombination(availableLevels, combinations);
|
||||||
|
if (tc == null) {
|
||||||
|
System.out.println("INFO: no more combinations available");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
System.out.println("INFO: Running testcase for: " + tc);
|
||||||
|
new SegmentedCodeCacheDtraceTest().runTest(tc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MethodData {
|
||||||
|
|
||||||
|
public final int compileLevel;
|
||||||
|
public final boolean isInlined;
|
||||||
|
public final String name;
|
||||||
|
|
||||||
|
public MethodData(String name, int compileLevel, boolean isInlined) {
|
||||||
|
this.name = name;
|
||||||
|
this.compileLevel = compileLevel;
|
||||||
|
this.isInlined = isInlined;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == null || !(o instanceof MethodData)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MethodData md = (MethodData) o;
|
||||||
|
return md.compileLevel == compileLevel
|
||||||
|
&& md.isInlined == isInlined
|
||||||
|
&& md.name.equals(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return 100 * name.hashCode() + 10 * compileLevel + (isInlined ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name + " " + compileLevel + " " + isInlined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestCombination {
|
||||||
|
|
||||||
|
private final Map<String, MethodData> data;
|
||||||
|
|
||||||
|
public TestCombination(int compLevels[], boolean inlines[]) {
|
||||||
|
Map<String, MethodData> d = new HashMap<>();
|
||||||
|
for (int i = 0; i < MLIST.size(); i++) {
|
||||||
|
d.put(MLIST.get(i).getName(), new MethodData(MLIST.get(i).getName(),
|
||||||
|
compLevels[i], inlines[i]));
|
||||||
|
}
|
||||||
|
data = Collections.unmodifiableMap(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == null || !(o instanceof TestCombination)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TestCombination second = (TestCombination) o;
|
||||||
|
return second.data.equals(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int sum = 0;
|
||||||
|
for (MethodData md : data.values()) {
|
||||||
|
sum += md.hashCode();
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMethodDescString(MethodData md) {
|
||||||
|
return (md == null)
|
||||||
|
? null
|
||||||
|
: String.format("Method %s compilation level %d and %s",
|
||||||
|
md.name, md.compileLevel,
|
||||||
|
md.isInlined ? "inlined" : "not inlined");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return data.values().stream().map(m -> getMethodDescString(m))
|
||||||
|
.collect(Collectors.joining(Utils.NEW_LINE,
|
||||||
|
"Combination: ", ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SegmentedCodeCacheDtraceResultsAnalyzer
|
||||||
|
implements DtraceResultsAnalyzer {
|
||||||
|
|
||||||
|
private static final int EXPECTED_MATCH_COUNT = 2;
|
||||||
|
|
||||||
|
private final Pattern checkPattern;
|
||||||
|
|
||||||
|
public SegmentedCodeCacheDtraceResultsAnalyzer() {
|
||||||
|
String workerClassRegExp = "\\s*" + WORKER_CLASS_NAME + "\\.";
|
||||||
|
String delimeter = "\\(\\)V\\*?" + workerClassRegExp;
|
||||||
|
String suffix = "test\\(\\)V\\*?" + workerClassRegExp
|
||||||
|
+ "main\\(\\[Ljava\\/lang\\/String;\\)V";
|
||||||
|
StringBuilder sb = new StringBuilder(workerClassRegExp);
|
||||||
|
// method order is important, so, going from list tail to head,
|
||||||
|
// accoring to call order representation in stacktrace
|
||||||
|
for (int i = MLIST.size() - 1; i > -1; i--) {
|
||||||
|
sb.append(MLIST.get(i).getName()).append(delimeter);
|
||||||
|
}
|
||||||
|
sb.append(suffix);
|
||||||
|
checkPattern = Pattern.compile(sb.toString());
|
||||||
|
/* such pattern match should pass on a stacktrace like
|
||||||
|
CPU ID FUNCTION:NAME
|
||||||
|
0 53573 __1cNSharedRuntimeTdtrace_method_entry6FpnKJavaThread_pnGMethod__i_:method-entry ustack:
|
||||||
|
|
||||||
|
libjvm.so`__1cNSharedRuntimeTdtrace_method_entry6FpnKJavaThread_pnGMethod__i_+0x39c
|
||||||
|
SegmentedCodeCacheDtraceTestWorker.baz()V*
|
||||||
|
SegmentedCodeCacheDtraceTestWorker.bar()V
|
||||||
|
SegmentedCodeCacheDtraceTestWorker.foo()V*
|
||||||
|
SegmentedCodeCacheDtraceTestWorker.test()V
|
||||||
|
SegmentedCodeCacheDtraceTestWorker.main([Ljava/lang/String;)V
|
||||||
|
0xffffffff6b0004b8
|
||||||
|
libjvm.so`__1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v_+0x94c
|
||||||
|
libjvm.so`__1cRjni_invoke_static6FpnHJNIEnv__pnJJavaValue_pnI_jobject_nLJNICallType_pnK_jmethodID_pnSJNI_ArgumentPusher_pnGThread__v_+0xa64
|
||||||
|
libjvm.so`jni_CallStaticVoidMethod+0x508
|
||||||
|
libjli.so`JavaMain+0x584
|
||||||
|
libc.so.1`_lwp_start
|
||||||
|
jstack:
|
||||||
|
|
||||||
|
libjvm.so`__1cNSharedRuntimeTdtrace_method_entry6FpnKJavaThread_pnGMethod__i_+0x39c
|
||||||
|
SegmentedCodeCacheDtraceTestWorker.baz()V*
|
||||||
|
SegmentedCodeCacheDtraceTestWorker.bar()V
|
||||||
|
SegmentedCodeCacheDtraceTestWorker.foo()V*
|
||||||
|
SegmentedCodeCacheDtraceTestWorker.test()V
|
||||||
|
SegmentedCodeCacheDtraceTestWorker.main([Ljava/lang/String;)V
|
||||||
|
0xffffffff6b0004b8
|
||||||
|
libjvm.so`__1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v_+0x94c
|
||||||
|
libjvm.so`__1cRjni_invoke_static6FpnHJNIEnv__pnJJavaValue_pnI_jobject_nLJNICallType_pnK_jmethodID_pnSJNI_ArgumentPusher_pnGThread__v_+0xa64
|
||||||
|
libjvm.so`jni_CallStaticVoidMethod+0x508
|
||||||
|
libjli.so`JavaMain+0x584
|
||||||
|
libc.so.1`_lwp_start
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<String> loadLog(String dtraceOutFile) throws IOException {
|
||||||
|
return Files.readAllLines(Paths.get(dtraceOutFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void analyze(OutputAnalyzer oa, String dtraceOutFilePath) {
|
||||||
|
oa.shouldHaveExitValue(0);
|
||||||
|
List<String> dOut;
|
||||||
|
try {
|
||||||
|
dOut = loadLog(dtraceOutFilePath);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new Error("Can't load log", e);
|
||||||
|
}
|
||||||
|
StringBuilder allDtraceOutput = new StringBuilder();
|
||||||
|
for (String entry : dOut) {
|
||||||
|
allDtraceOutput.append(entry);
|
||||||
|
}
|
||||||
|
int matchCount = getMatchCount(allDtraceOutput.toString());
|
||||||
|
Asserts.assertEQ(matchCount, EXPECTED_MATCH_COUNT,
|
||||||
|
"Unexpected output match amount. expected: "
|
||||||
|
+ EXPECTED_MATCH_COUNT + " but found " + matchCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getMatchCount(String source) {
|
||||||
|
Matcher m = checkPattern.matcher(source);
|
||||||
|
int matchCount = 0;
|
||||||
|
while (m.find()) {
|
||||||
|
matchCount++;
|
||||||
|
}
|
||||||
|
return matchCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
#!/usr/sbin/dtrace -s
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
hotspot$target:::method-entry
|
||||||
|
/ copyinstr(arg3, arg4) == "baz" /
|
||||||
|
{
|
||||||
|
printf("ustack:\n");
|
||||||
|
ustack(50, 500);
|
||||||
|
printf("jstack:\n");
|
||||||
|
jstack();
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Utils;
|
||||||
|
import java.lang.reflect.Executable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
|
||||||
|
public class SegmentedCodeCacheDtraceTestWorker {
|
||||||
|
|
||||||
|
private static final String METHOD1_NAME = "foo";
|
||||||
|
private static final String METHOD2_NAME = "bar";
|
||||||
|
private static final String METHOD3_NAME = "baz";
|
||||||
|
public static final List<Executable> TESTED_METHODS_LIST;
|
||||||
|
private final WhiteBox wb;
|
||||||
|
private final int compLevels[];
|
||||||
|
|
||||||
|
static {
|
||||||
|
List<Executable> methods = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
// method order is important. Need to place methods in call order,
|
||||||
|
// to be able to verify results later
|
||||||
|
methods.add(SegmentedCodeCacheDtraceTestWorker.class.getMethod(METHOD1_NAME));
|
||||||
|
methods.add(SegmentedCodeCacheDtraceTestWorker.class.getMethod(METHOD2_NAME));
|
||||||
|
methods.add(SegmentedCodeCacheDtraceTestWorker.class.getMethod(METHOD3_NAME));
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
throw new Error("TESTBUG: no expected method found", e);
|
||||||
|
}
|
||||||
|
TESTED_METHODS_LIST = Collections.unmodifiableList(methods);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static final boolean BACKGROUND_COMPILATION
|
||||||
|
= WhiteBox.getWhiteBox().getBooleanVMFlag("BackgroundCompilation");
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
if (args.length != 2 * TESTED_METHODS_LIST.size()) {
|
||||||
|
throw new Error("Usage: java <thisClass> <fooCompLevel> <fooInlined>"
|
||||||
|
+ "<barCompLevel> <barInlined> "
|
||||||
|
+ "<bazCompLevel> <bazInlined>");
|
||||||
|
} else {
|
||||||
|
int compLevels[] = new int[TESTED_METHODS_LIST.size()];
|
||||||
|
boolean inlines[] = new boolean[TESTED_METHODS_LIST.size()];
|
||||||
|
for (int i = 0; i < TESTED_METHODS_LIST.size(); i++) {
|
||||||
|
compLevels[i] = Integer.parseInt(args[2 * i]);
|
||||||
|
inlines[i] = Boolean.parseBoolean(args[2 * i + 1]);
|
||||||
|
}
|
||||||
|
new SegmentedCodeCacheDtraceTestWorker(compLevels, inlines).test();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SegmentedCodeCacheDtraceTestWorker(int compLevels[], boolean inlines[]) {
|
||||||
|
wb = WhiteBox.getWhiteBox();
|
||||||
|
this.compLevels = Arrays.copyOf(compLevels, compLevels.length);
|
||||||
|
for (int i = 0; i < compLevels.length; i++) {
|
||||||
|
if (inlines[i]) {
|
||||||
|
wb.testSetForceInlineMethod(TESTED_METHODS_LIST.get(i), true);
|
||||||
|
} else {
|
||||||
|
wb.testSetDontInlineMethod(TESTED_METHODS_LIST.get(i), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void waitForCompilation(Executable executable, int compLevel) {
|
||||||
|
if (compLevel > 0) {
|
||||||
|
Utils.waitForCondition(() -> wb.isMethodCompiled(executable));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void test() {
|
||||||
|
for (int i = 0; i < TESTED_METHODS_LIST.size(); i++) {
|
||||||
|
Executable method = TESTED_METHODS_LIST.get(i);
|
||||||
|
int compLevel = compLevels[i];
|
||||||
|
wb.enqueueMethodForCompilation(method, compLevel);
|
||||||
|
waitForCompilation(method, compLevel);
|
||||||
|
}
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void foo() {
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void bar() {
|
||||||
|
baz();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void baz() {
|
||||||
|
System.out.println("Reached baz method");
|
||||||
|
}
|
||||||
|
}
|
47
hotspot/test/compiler/codecache/jmx/BeanTypeTest.java
Normal file
47
hotspot/test/compiler/codecache/jmx/BeanTypeTest.java
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import java.lang.management.MemoryType;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test BeanTypeTest
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build BeanTypeTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache BeanTypeTest
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache BeanTypeTest
|
||||||
|
* @summary verify types of code cache memory pool bean
|
||||||
|
*/
|
||||||
|
public class BeanTypeTest {
|
||||||
|
|
||||||
|
public static void main(String args[]) {
|
||||||
|
for (BlobType bt : BlobType.getAvailable()) {
|
||||||
|
Asserts.assertEQ(MemoryType.NON_HEAP, bt.getMemoryPool().getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
101
hotspot/test/compiler/codecache/jmx/CodeCacheUtils.java
Normal file
101
hotspot/test/compiler/codecache/jmx/CodeCacheUtils.java
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Utils;
|
||||||
|
import java.lang.management.MemoryPoolMXBean;
|
||||||
|
import javax.management.Notification;
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
import sun.hotspot.code.CodeBlob;
|
||||||
|
|
||||||
|
public final class CodeCacheUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value to be used for code heap allocation
|
||||||
|
*/
|
||||||
|
public static final int ALLOCATION_SIZE
|
||||||
|
= Integer.getInteger("codecache.allocation.size", 100);
|
||||||
|
public static final WhiteBox WB = WhiteBox.getWhiteBox();
|
||||||
|
public static final long SEGMENT_SIZE
|
||||||
|
= WhiteBox.getWhiteBox().getUintxVMFlag("CodeCacheSegmentSize");
|
||||||
|
public static final long MIN_BLOCK_LENGTH
|
||||||
|
= WhiteBox.getWhiteBox().getUintxVMFlag("CodeCacheMinBlockLength");
|
||||||
|
public static final long MIN_ALLOCATION = SEGMENT_SIZE * MIN_BLOCK_LENGTH;
|
||||||
|
|
||||||
|
private CodeCacheUtils() {
|
||||||
|
// To prevent from instantiation
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final void hitUsageThreshold(MemoryPoolMXBean bean,
|
||||||
|
BlobType btype) {
|
||||||
|
long initialSize = bean.getUsage().getUsed();
|
||||||
|
bean.setUsageThreshold(initialSize + 1);
|
||||||
|
long usageThresholdCount = bean.getUsageThresholdCount();
|
||||||
|
long addr = WB.allocateCodeBlob(1, btype.id);
|
||||||
|
WB.fullGC();
|
||||||
|
Utils.waitForCondition(()
|
||||||
|
-> bean.getUsageThresholdCount() == usageThresholdCount + 1);
|
||||||
|
WB.freeCodeBlob(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final long getHeaderSize(BlobType btype) {
|
||||||
|
long addr = WB.allocateCodeBlob(0, btype.id);
|
||||||
|
int size = CodeBlob.getCodeBlob(addr).size;
|
||||||
|
WB.freeCodeBlob(addr);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getPoolNameFromNotification(
|
||||||
|
Notification notification) {
|
||||||
|
return ((javax.management.openmbean.CompositeDataSupport)
|
||||||
|
notification.getUserData()).get("poolName").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isAvailableCodeHeapPoolName(String name) {
|
||||||
|
return BlobType.getAvailable().stream()
|
||||||
|
.map(BlobType::getMemoryPool)
|
||||||
|
.map(MemoryPoolMXBean::getName)
|
||||||
|
.filter(name::equals)
|
||||||
|
.findAny().isPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A "non-nmethods" code heap is used by interpreter during bytecode
|
||||||
|
* execution, thus, it can't be predicted if this code heap usage will be
|
||||||
|
* increased or not. Same goes for 'All'.
|
||||||
|
*
|
||||||
|
* @param btype BlobType to be checked
|
||||||
|
* @return boolean value, true if respective code heap is predictable
|
||||||
|
*/
|
||||||
|
public static boolean isCodeHeapPredictable(BlobType btype) {
|
||||||
|
return btype == BlobType.MethodNonProfiled
|
||||||
|
|| btype == BlobType.MethodProfiled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void disableCollectionUsageThresholds(){
|
||||||
|
BlobType.getAvailable().stream()
|
||||||
|
.map(BlobType::getMemoryPool)
|
||||||
|
.filter(MemoryPoolMXBean::isCollectionUsageThresholdSupported)
|
||||||
|
.forEach(b -> b.setCollectionUsageThreshold(0L));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test CodeHeapBeanPresenceTest
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build CodeHeapBeanPresenceTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache CodeHeapBeanPresenceTest
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache CodeHeapBeanPresenceTest
|
||||||
|
* @summary verify CodeHeap bean presence
|
||||||
|
*/
|
||||||
|
public class CodeHeapBeanPresenceTest {
|
||||||
|
|
||||||
|
public static void main(String args[]) {
|
||||||
|
EnumSet<BlobType> shouldBeAvailable = BlobType.getAvailable();
|
||||||
|
EnumSet<BlobType> shouldNotBeAvailable
|
||||||
|
= EnumSet.complementOf(shouldBeAvailable);
|
||||||
|
for (BlobType btype : shouldBeAvailable) {
|
||||||
|
Asserts.assertNotNull(btype.getMemoryPool(),
|
||||||
|
"Can't find memory pool for " + btype.name());
|
||||||
|
}
|
||||||
|
for (BlobType btype : shouldNotBeAvailable) {
|
||||||
|
Asserts.assertNull(btype.getMemoryPool(),
|
||||||
|
"Memory pool unexpected for " + btype.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
109
hotspot/test/compiler/codecache/jmx/GetUsageTest.java
Normal file
109
hotspot/test/compiler/codecache/jmx/GetUsageTest.java
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import java.lang.management.MemoryPoolMXBean;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test GetUsageTest
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build GetUsageTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:CompileCommand=compileonly,null::*
|
||||||
|
* -XX:-UseCodeCacheFlushing -XX:-MethodFlushing -XX:+SegmentedCodeCache
|
||||||
|
* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI GetUsageTest
|
||||||
|
* @summary testing of getUsage() for segmented code cache
|
||||||
|
*/
|
||||||
|
public class GetUsageTest {
|
||||||
|
|
||||||
|
private final BlobType btype;
|
||||||
|
private final int allocateSize;
|
||||||
|
|
||||||
|
public GetUsageTest(BlobType btype, int allocSize) {
|
||||||
|
this.btype = btype;
|
||||||
|
this.allocateSize = allocSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
for (BlobType btype : BlobType.getAvailable()) {
|
||||||
|
if (CodeCacheUtils.isCodeHeapPredictable(btype)) {
|
||||||
|
for (int allocSize = 10; allocSize < 100000; allocSize *= 10) {
|
||||||
|
new GetUsageTest(btype, allocSize).runTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final Map<MemoryPoolMXBean, Long> getBeanUsages() {
|
||||||
|
Map<MemoryPoolMXBean, Long> beanUsages = new HashMap<>();
|
||||||
|
for (BlobType bt : BlobType.getAvailable()) {
|
||||||
|
beanUsages.put(bt.getMemoryPool(),
|
||||||
|
bt.getMemoryPool().getUsage().getUsed());
|
||||||
|
}
|
||||||
|
return beanUsages;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runTest() {
|
||||||
|
MemoryPoolMXBean[] predictableBeans = BlobType.getAvailable().stream()
|
||||||
|
.filter(CodeCacheUtils::isCodeHeapPredictable)
|
||||||
|
.map(BlobType::getMemoryPool)
|
||||||
|
.toArray(MemoryPoolMXBean[]::new);
|
||||||
|
Map<MemoryPoolMXBean, Long> initial = getBeanUsages();
|
||||||
|
long addr = 0;
|
||||||
|
try {
|
||||||
|
addr = CodeCacheUtils.WB.allocateCodeBlob(allocateSize, btype.id);
|
||||||
|
Map<MemoryPoolMXBean, Long> current = getBeanUsages();
|
||||||
|
long blockCount = Math.floorDiv(allocateSize
|
||||||
|
+ CodeCacheUtils.getHeaderSize(btype)
|
||||||
|
+ CodeCacheUtils.SEGMENT_SIZE - 1, CodeCacheUtils.SEGMENT_SIZE);
|
||||||
|
long usageUpperEstimate = Math.max(blockCount,
|
||||||
|
CodeCacheUtils.MIN_BLOCK_LENGTH) * CodeCacheUtils.SEGMENT_SIZE;
|
||||||
|
for (MemoryPoolMXBean entry : predictableBeans) {
|
||||||
|
long diff = current.get(entry) - initial.get(entry);
|
||||||
|
if (entry.equals(btype.getMemoryPool())) {
|
||||||
|
Asserts.assertFalse(diff <= 0L || diff > usageUpperEstimate,
|
||||||
|
String.format("Pool %s usage increase was reported "
|
||||||
|
+ "unexpectedly as increased by %d using "
|
||||||
|
+ "allocation size %d", entry.getName(),
|
||||||
|
diff, allocateSize));
|
||||||
|
} else {
|
||||||
|
Asserts.assertEQ(diff, 0L,
|
||||||
|
String.format("Pool %s usage changed unexpectedly while"
|
||||||
|
+ " trying to increase: %s using allocation "
|
||||||
|
+ "size %d", entry.getName(),
|
||||||
|
btype.getMemoryPool().getName(), allocateSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (addr != 0) {
|
||||||
|
CodeCacheUtils.WB.freeCodeBlob(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.printf("INFO: Scenario finished successfully for %s%n",
|
||||||
|
btype.getMemoryPool().getName());
|
||||||
|
}
|
||||||
|
}
|
107
hotspot/test/compiler/codecache/jmx/InitialAndMaxUsageTest.java
Normal file
107
hotspot/test/compiler/codecache/jmx/InitialAndMaxUsageTest.java
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import java.lang.management.MemoryPoolMXBean;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test InitialAndMaxUsageTest
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build InitialAndMaxUsageTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:-UseCodeCacheFlushing
|
||||||
|
* -XX:-MethodFlushing -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
|
* -XX:+SegmentedCodeCache -XX:CompileCommand=compileonly,null::*
|
||||||
|
* InitialAndMaxUsageTest
|
||||||
|
* @summary testing of initial and max usage
|
||||||
|
*/
|
||||||
|
public class InitialAndMaxUsageTest {
|
||||||
|
|
||||||
|
private static final double CACHE_USAGE_COEF = 0.95d;
|
||||||
|
private final BlobType btype;
|
||||||
|
private final boolean lowerBoundIsZero;
|
||||||
|
private final long maxSize;
|
||||||
|
|
||||||
|
public InitialAndMaxUsageTest(BlobType btype) {
|
||||||
|
this.btype = btype;
|
||||||
|
this.maxSize = btype.getSize();
|
||||||
|
/* Only profiled code cache initial size should be 0, because of
|
||||||
|
-XX:CompileCommand=compileonly,null::* non-methods might be not empty,
|
||||||
|
as well as non-profiled methods, because it's used as fallback in
|
||||||
|
case non-methods is full */
|
||||||
|
lowerBoundIsZero = btype == BlobType.MethodProfiled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
for (BlobType btype : BlobType.getAvailable()) {
|
||||||
|
new InitialAndMaxUsageTest(btype).runTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillWithSize(long size, List<Long> blobs) {
|
||||||
|
long blob;
|
||||||
|
while ((blob = CodeCacheUtils.WB.allocateCodeBlob(size, btype.id))
|
||||||
|
!= 0L) {
|
||||||
|
blobs.add(blob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runTest() {
|
||||||
|
long headerSize = CodeCacheUtils.getHeaderSize(btype);
|
||||||
|
MemoryPoolMXBean bean = btype.getMemoryPool();
|
||||||
|
long initialUsage = btype.getMemoryPool().getUsage().getUsed();
|
||||||
|
System.out.printf("INFO: trying to test %s of max size %d and initial"
|
||||||
|
+ " usage %d%n", bean.getName(), maxSize, initialUsage);
|
||||||
|
Asserts.assertLT(initialUsage + headerSize + 1L, maxSize,
|
||||||
|
"Initial usage is close to total size for " + bean.getName());
|
||||||
|
if (lowerBoundIsZero) {
|
||||||
|
Asserts.assertEQ(initialUsage, 0L, "Unexpected initial usage");
|
||||||
|
}
|
||||||
|
ArrayList<Long> blobs = new ArrayList<>();
|
||||||
|
long minAllocationUnit = CodeCacheUtils.MIN_ALLOCATION - headerSize;
|
||||||
|
/* now filling code cache with large-sized allocation first, since
|
||||||
|
lots of small allocations takes too much time, so, just a small
|
||||||
|
optimization */
|
||||||
|
try {
|
||||||
|
for (int coef = 1000000; coef > 0; coef /= 10) {
|
||||||
|
fillWithSize(coef * minAllocationUnit, blobs);
|
||||||
|
}
|
||||||
|
Asserts.assertGT((double) bean.getUsage().getUsed(),
|
||||||
|
CACHE_USAGE_COEF * maxSize, String.format("Unable to fill "
|
||||||
|
+ "more than %f of %s. Reported usage is %d ",
|
||||||
|
CACHE_USAGE_COEF, bean.getName(),
|
||||||
|
bean.getUsage().getUsed()));
|
||||||
|
} finally {
|
||||||
|
for (long entry : blobs) {
|
||||||
|
CodeCacheUtils.WB.freeCodeBlob(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.printf("INFO: Scenario finished successfully for %s%n",
|
||||||
|
bean.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
64
hotspot/test/compiler/codecache/jmx/ManagerNamesTest.java
Normal file
64
hotspot/test/compiler/codecache/jmx/ManagerNamesTest.java
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import java.lang.management.MemoryPoolMXBean;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test ManagerNamesTest
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build ManagerNamesTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache ManagerNamesTest
|
||||||
|
* * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache ManagerNamesTest
|
||||||
|
* @summary verify getMemoryManageNames calls in case of segmented code cache
|
||||||
|
*/
|
||||||
|
public class ManagerNamesTest {
|
||||||
|
|
||||||
|
private final MemoryPoolMXBean bean;
|
||||||
|
private final static String POOL_NAME = "CodeCacheManager";
|
||||||
|
|
||||||
|
public static void main(String args[]) {
|
||||||
|
for (BlobType btype : BlobType.getAvailable()) {
|
||||||
|
new ManagerNamesTest(btype).runTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ManagerNamesTest(BlobType btype) {
|
||||||
|
bean = btype.getMemoryPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runTest() {
|
||||||
|
String[] names = bean.getMemoryManagerNames();
|
||||||
|
Asserts.assertEQ(names.length, 1,
|
||||||
|
"Unexpected length of MemoryManagerNames");
|
||||||
|
Asserts.assertEQ(POOL_NAME, names[0],
|
||||||
|
"Unexpected value of MemoryManagerName");
|
||||||
|
System.out.printf("INFO: Scenario finished successfully for %s%n",
|
||||||
|
bean.getName());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.management.MemoryManagerMXBean;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test MemoryPoolsPresenceTest
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build MemoryPoolsPresenceTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache MemoryPoolsPresenceTest
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache MemoryPoolsPresenceTest
|
||||||
|
* @summary verify that MemoryManagerMXBean exists for every code cache segment
|
||||||
|
*/
|
||||||
|
public class MemoryPoolsPresenceTest {
|
||||||
|
|
||||||
|
private static final String CC_MANAGER = "CodeCacheManager";
|
||||||
|
private final Map<String, Integer> counters = new HashMap<>();
|
||||||
|
|
||||||
|
public static void main(String args[]) {
|
||||||
|
new MemoryPoolsPresenceTest().runTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runTest() {
|
||||||
|
List<MemoryManagerMXBean> beans
|
||||||
|
= ManagementFactory.getMemoryManagerMXBeans();
|
||||||
|
Optional<MemoryManagerMXBean> any = beans
|
||||||
|
.stream()
|
||||||
|
.filter(bean -> CC_MANAGER.equals(bean.getName()))
|
||||||
|
.findAny();
|
||||||
|
Asserts.assertTrue(any.isPresent(), "Bean not found: " + CC_MANAGER);
|
||||||
|
MemoryManagerMXBean ccManager = any.get();
|
||||||
|
Asserts.assertNotNull(ccManager, "Found null for " + CC_MANAGER);
|
||||||
|
String names[] = ccManager.getMemoryPoolNames();
|
||||||
|
for (String name : names) {
|
||||||
|
counters.put(name, counters.containsKey(name)
|
||||||
|
? counters.get(name) + 1 : 1);
|
||||||
|
}
|
||||||
|
for (BlobType btype : BlobType.getAvailable()) {
|
||||||
|
Asserts.assertEQ(counters.get(btype.getMemoryPool().getName()), 1,
|
||||||
|
"Found unexpected amount of beans for pool "
|
||||||
|
+ btype.getMemoryPool().getName());
|
||||||
|
}
|
||||||
|
Asserts.assertEQ(BlobType.getAvailable().size(),
|
||||||
|
counters.keySet().size(), "Unexpected amount of bean names");
|
||||||
|
}
|
||||||
|
}
|
97
hotspot/test/compiler/codecache/jmx/PeakUsageTest.java
Normal file
97
hotspot/test/compiler/codecache/jmx/PeakUsageTest.java
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import java.lang.management.MemoryPoolMXBean;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test PeakUsageTest
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build PeakUsageTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache
|
||||||
|
* -XX:CompileCommand=compileonly,null::* PeakUsageTest
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache
|
||||||
|
* -XX:CompileCommand=compileonly,null::* PeakUsageTest
|
||||||
|
* @summary testing of getPeakUsage() and resetPeakUsage for
|
||||||
|
* segmented code cache
|
||||||
|
*/
|
||||||
|
public class PeakUsageTest {
|
||||||
|
|
||||||
|
private final BlobType btype;
|
||||||
|
|
||||||
|
public PeakUsageTest(BlobType btype) {
|
||||||
|
this.btype = btype;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
for (BlobType btype : BlobType.getAvailable()) {
|
||||||
|
if (CodeCacheUtils.isCodeHeapPredictable(btype)) {
|
||||||
|
new PeakUsageTest(btype).runTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runTest() {
|
||||||
|
MemoryPoolMXBean bean = btype.getMemoryPool();
|
||||||
|
bean.resetPeakUsage();
|
||||||
|
long addr = CodeCacheUtils.WB.allocateCodeBlob(
|
||||||
|
CodeCacheUtils.ALLOCATION_SIZE, btype.id);
|
||||||
|
long newPeakUsage = bean.getPeakUsage().getUsed();
|
||||||
|
try {
|
||||||
|
Asserts.assertEQ(newPeakUsage, bean.getUsage().getUsed(),
|
||||||
|
"Peak usage does not match usage after allocation for "
|
||||||
|
+ bean.getName());
|
||||||
|
} finally {
|
||||||
|
if (addr != 0) {
|
||||||
|
CodeCacheUtils.WB.freeCodeBlob(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Asserts.assertEQ(newPeakUsage, bean.getPeakUsage().getUsed(),
|
||||||
|
"Code cache peak usage has changed after usage decreased for "
|
||||||
|
+ bean.getName());
|
||||||
|
bean.resetPeakUsage();
|
||||||
|
Asserts.assertEQ(bean.getPeakUsage().getUsed(),
|
||||||
|
bean.getUsage().getUsed(),
|
||||||
|
"Code cache peak usage is not equal to usage after reset for "
|
||||||
|
+ bean.getName());
|
||||||
|
long addr2 = CodeCacheUtils.WB.allocateCodeBlob(
|
||||||
|
CodeCacheUtils.ALLOCATION_SIZE, btype.id);
|
||||||
|
try {
|
||||||
|
Asserts.assertEQ(bean.getPeakUsage().getUsed(),
|
||||||
|
bean.getUsage().getUsed(),
|
||||||
|
"Code cache peak usage is not equal to usage after fresh "
|
||||||
|
+ "allocation for " + bean.getName());
|
||||||
|
} finally {
|
||||||
|
if (addr2 != 0) {
|
||||||
|
CodeCacheUtils.WB.freeCodeBlob(addr2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.printf("INFO: Scenario finished successfully for %s%n",
|
||||||
|
bean.getName());
|
||||||
|
}
|
||||||
|
}
|
131
hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java
Normal file
131
hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import com.oracle.java.testlibrary.Utils;
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.management.MemoryNotificationInfo;
|
||||||
|
import java.lang.management.MemoryPoolMXBean;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import javax.management.ListenerNotFoundException;
|
||||||
|
import javax.management.Notification;
|
||||||
|
import javax.management.NotificationEmitter;
|
||||||
|
import javax.management.NotificationListener;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test PoolsIndependenceTest
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build PoolsIndependenceTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:-UseCodeCacheFlushing
|
||||||
|
* -XX:-MethodFlushing -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
|
* -XX:+SegmentedCodeCache PoolsIndependenceTest
|
||||||
|
* @summary testing of getUsageThreshold()
|
||||||
|
*/
|
||||||
|
public class PoolsIndependenceTest implements NotificationListener {
|
||||||
|
|
||||||
|
private final Map<String, AtomicInteger> counters;
|
||||||
|
private final BlobType btype;
|
||||||
|
private volatile long lastEventTimestamp;
|
||||||
|
|
||||||
|
public PoolsIndependenceTest(BlobType btype) {
|
||||||
|
counters = new HashMap<>();
|
||||||
|
for (BlobType bt : BlobType.getAvailable()) {
|
||||||
|
counters.put(bt.getMemoryPool().getName(), new AtomicInteger(0));
|
||||||
|
}
|
||||||
|
this.btype = btype;
|
||||||
|
lastEventTimestamp = 0;
|
||||||
|
CodeCacheUtils.disableCollectionUsageThresholds();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
for (BlobType bt : BlobType.getAvailable()) {
|
||||||
|
new PoolsIndependenceTest(bt).runTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runTest() {
|
||||||
|
MemoryPoolMXBean bean = btype.getMemoryPool();
|
||||||
|
((NotificationEmitter) ManagementFactory.getMemoryMXBean()).
|
||||||
|
addNotificationListener(this, null, null);
|
||||||
|
bean.setUsageThreshold(bean.getUsage().getUsed() + 1);
|
||||||
|
long beginTimestamp = System.currentTimeMillis();
|
||||||
|
CodeCacheUtils.WB.allocateCodeBlob(
|
||||||
|
CodeCacheUtils.ALLOCATION_SIZE, btype.id);
|
||||||
|
CodeCacheUtils.WB.fullGC();
|
||||||
|
/* waiting for expected event to be received plus double the time took
|
||||||
|
to receive expected event(for possible unexpected) and
|
||||||
|
plus 1 second in case expected event received (almost)immediately */
|
||||||
|
Utils.waitForCondition(() -> {
|
||||||
|
long currentTimestamp = System.currentTimeMillis();
|
||||||
|
int eventsCount
|
||||||
|
= counters.get(btype.getMemoryPool().getName()).get();
|
||||||
|
if (eventsCount > 0) {
|
||||||
|
if (eventsCount > 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
long timeLastEventTook
|
||||||
|
= beginTimestamp - lastEventTimestamp;
|
||||||
|
long timeoutValue
|
||||||
|
= 1000L + beginTimestamp + 3L * timeLastEventTook;
|
||||||
|
return currentTimestamp > timeoutValue;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
for (BlobType bt : BlobType.getAvailable()) {
|
||||||
|
int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0;
|
||||||
|
Asserts.assertEQ(counters.get(bt.getMemoryPool().getName()).get(),
|
||||||
|
expectedNotificationsAmount, String.format("Unexpected "
|
||||||
|
+ "amount of notifications for pool: %s",
|
||||||
|
bt.getMemoryPool().getName()));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
((NotificationEmitter) ManagementFactory.getMemoryMXBean()).
|
||||||
|
removeNotificationListener(this);
|
||||||
|
} catch (ListenerNotFoundException ex) {
|
||||||
|
throw new AssertionError("Can't remove notification listener", ex);
|
||||||
|
}
|
||||||
|
System.out.printf("INFO: Scenario with %s finished%n", bean.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleNotification(Notification notification, Object handback) {
|
||||||
|
String nType = notification.getType();
|
||||||
|
String poolName
|
||||||
|
= CodeCacheUtils.getPoolNameFromNotification(notification);
|
||||||
|
// consider code cache events only
|
||||||
|
if (CodeCacheUtils.isAvailableCodeHeapPoolName(poolName)) {
|
||||||
|
Asserts.assertEQ(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED,
|
||||||
|
nType, "Unexpected event received: " + nType);
|
||||||
|
// receiving events from available CodeCache-related beans only
|
||||||
|
if (counters.get(poolName) != null) {
|
||||||
|
counters.get(poolName).incrementAndGet();
|
||||||
|
lastEventTimestamp = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import com.oracle.java.testlibrary.Utils;
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.management.MemoryNotificationInfo;
|
||||||
|
import java.lang.management.MemoryPoolMXBean;
|
||||||
|
import javax.management.ListenerNotFoundException;
|
||||||
|
import javax.management.Notification;
|
||||||
|
import javax.management.NotificationEmitter;
|
||||||
|
import javax.management.NotificationListener;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test ThresholdNotificationsTest
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build ThresholdNotificationsTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:-UseCodeCacheFlushing
|
||||||
|
* -XX:-MethodFlushing -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
|
* -XX:+SegmentedCodeCache -XX:CompileCommand=compileonly,null::*
|
||||||
|
* ThresholdNotificationsTest
|
||||||
|
* @summary testing of getUsageThreshold()
|
||||||
|
*/
|
||||||
|
public class ThresholdNotificationsTest implements NotificationListener {
|
||||||
|
|
||||||
|
private final static long WAIT_TIME = 10000L;
|
||||||
|
private volatile long counter;
|
||||||
|
private final BlobType btype;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
for (BlobType bt : BlobType.getAvailable()) {
|
||||||
|
new ThresholdNotificationsTest(bt).runTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ThresholdNotificationsTest(BlobType btype) {
|
||||||
|
this.btype = btype;
|
||||||
|
counter = 0L;
|
||||||
|
CodeCacheUtils.disableCollectionUsageThresholds();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleNotification(Notification notification, Object handback) {
|
||||||
|
String nType = notification.getType();
|
||||||
|
String poolName
|
||||||
|
= CodeCacheUtils.getPoolNameFromNotification(notification);
|
||||||
|
// consider code cache events only
|
||||||
|
if (CodeCacheUtils.isAvailableCodeHeapPoolName(poolName)) {
|
||||||
|
Asserts.assertEQ(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED,
|
||||||
|
nType, "Unexpected event received: " + nType);
|
||||||
|
if (poolName.equals(btype.getMemoryPool().getName())) {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runTest() {
|
||||||
|
int iterationsCount =
|
||||||
|
Integer.getInteger("com.oracle.java.testlibrary.iterations", 1);
|
||||||
|
MemoryPoolMXBean bean = btype.getMemoryPool();
|
||||||
|
((NotificationEmitter) ManagementFactory.getMemoryMXBean()).
|
||||||
|
addNotificationListener(this, null, null);
|
||||||
|
for (int i = 0; i < iterationsCount; i++) {
|
||||||
|
CodeCacheUtils.hitUsageThreshold(bean, btype);
|
||||||
|
}
|
||||||
|
Asserts.assertTrue(
|
||||||
|
Utils.waitForCondition(
|
||||||
|
() -> counter == iterationsCount, WAIT_TIME),
|
||||||
|
"Couldn't receive expected notifications count");
|
||||||
|
try {
|
||||||
|
((NotificationEmitter) ManagementFactory.getMemoryMXBean()).
|
||||||
|
removeNotificationListener(this);
|
||||||
|
} catch (ListenerNotFoundException ex) {
|
||||||
|
throw new AssertionError("Can't remove notification listener", ex);
|
||||||
|
}
|
||||||
|
System.out.printf("INFO: Scenario finished successfully for %s%n",
|
||||||
|
bean.getName());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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 UsageThresholdExceededSeveralTimesTest
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build UsageThresholdExceededTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:-UseCodeCacheFlushing
|
||||||
|
* -XX:-MethodFlushing -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
|
* -XX:+SegmentedCodeCache -XX:CompileCommand=compileonly,null::*
|
||||||
|
* -Dcom.oracle.java.testlibrary.iterations=10 UsageThresholdExceededTest
|
||||||
|
* @summary verifying that getUsageThresholdCount() returns correct value
|
||||||
|
* after threshold has been hit several times
|
||||||
|
*/
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import java.lang.management.MemoryPoolMXBean;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test UsageThresholdExceededTest
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build UsageThresholdExceededTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache -XX:-UseCodeCacheFlushing
|
||||||
|
* -XX:-MethodFlushing -XX:CompileCommand=compileonly,null::*
|
||||||
|
* UsageThresholdExceededTest
|
||||||
|
* @summary verifying that getUsageThresholdCount() returns correct value
|
||||||
|
* after threshold has been hit
|
||||||
|
*/
|
||||||
|
public class UsageThresholdExceededTest {
|
||||||
|
|
||||||
|
protected final int iterations;
|
||||||
|
private final BlobType btype;
|
||||||
|
|
||||||
|
public UsageThresholdExceededTest(BlobType btype, int iterations) {
|
||||||
|
this.btype = btype;
|
||||||
|
this.iterations = iterations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int iterationsCount =
|
||||||
|
Integer.getInteger("com.oracle.java.testlibrary.iterations", 1);
|
||||||
|
for (BlobType btype : BlobType.getAvailable()) {
|
||||||
|
if (CodeCacheUtils.isCodeHeapPredictable(btype)) {
|
||||||
|
new UsageThresholdExceededTest(btype, iterationsCount)
|
||||||
|
.runTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runTest() {
|
||||||
|
MemoryPoolMXBean bean = btype.getMemoryPool();
|
||||||
|
long oldValue = bean.getUsageThresholdCount();
|
||||||
|
for (int i = 0; i < iterations; i++) {
|
||||||
|
CodeCacheUtils.hitUsageThreshold(bean, btype);
|
||||||
|
}
|
||||||
|
Asserts.assertEQ(bean.getUsageThresholdCount(), oldValue + iterations,
|
||||||
|
"Unexpected threshold usage count");
|
||||||
|
System.out.printf("INFO: Scenario finished successfully for %s%n",
|
||||||
|
bean.getName());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import java.lang.management.MemoryPoolMXBean;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test UsageThresholdIncreasedTest
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build UsageThresholdIncreasedTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache -XX:-UseCodeCacheFlushing
|
||||||
|
* -XX:-MethodFlushing -XX:CompileCommand=compileonly,null::*
|
||||||
|
* UsageThresholdIncreasedTest
|
||||||
|
* @summary verifying that threshold hasn't been hit after allocation smaller
|
||||||
|
* than threshold value and that threshold value can be changed
|
||||||
|
*/
|
||||||
|
public class UsageThresholdIncreasedTest {
|
||||||
|
|
||||||
|
private static final int ALLOCATION_STEP = 5;
|
||||||
|
private static final long THRESHOLD_STEP = ALLOCATION_STEP
|
||||||
|
* CodeCacheUtils.MIN_ALLOCATION;
|
||||||
|
private final BlobType btype;
|
||||||
|
|
||||||
|
public UsageThresholdIncreasedTest(BlobType btype) {
|
||||||
|
this.btype = btype;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
for (BlobType btype : BlobType.getAvailable()) {
|
||||||
|
new UsageThresholdIncreasedTest(btype).runTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkUsageThresholdCount(MemoryPoolMXBean bean, long count){
|
||||||
|
Asserts.assertEQ(bean.getUsageThresholdCount(), count,
|
||||||
|
String.format("Usage threshold was hit: %d times for %s "
|
||||||
|
+ "Threshold value: %d with current usage: %d",
|
||||||
|
bean.getUsageThresholdCount(), bean.getName(),
|
||||||
|
bean.getUsageThreshold(), bean.getUsage().getUsed()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runTest() {
|
||||||
|
long headerSize = CodeCacheUtils.getHeaderSize(btype);
|
||||||
|
long allocationUnit = CodeCacheUtils.MIN_ALLOCATION - headerSize;
|
||||||
|
MemoryPoolMXBean bean = btype.getMemoryPool();
|
||||||
|
long initialCount = bean.getUsageThresholdCount();
|
||||||
|
long initialSize = bean.getUsage().getUsed();
|
||||||
|
bean.setUsageThreshold(initialSize + THRESHOLD_STEP);
|
||||||
|
for (int i = 0; i < ALLOCATION_STEP - 1; i++) {
|
||||||
|
CodeCacheUtils.WB.allocateCodeBlob(allocationUnit, btype.id);
|
||||||
|
}
|
||||||
|
// Usage threshold check is triggered by GC cycle, so, call it
|
||||||
|
CodeCacheUtils.WB.fullGC();
|
||||||
|
checkUsageThresholdCount(bean, initialCount);
|
||||||
|
long filledSize = bean.getUsage().getUsed();
|
||||||
|
bean.setUsageThreshold(filledSize + THRESHOLD_STEP);
|
||||||
|
for (int i = 0; i < ALLOCATION_STEP - 1; i++) {
|
||||||
|
CodeCacheUtils.WB.allocateCodeBlob(allocationUnit, btype.id);
|
||||||
|
}
|
||||||
|
CodeCacheUtils.WB.fullGC();
|
||||||
|
checkUsageThresholdCount(bean, initialCount);
|
||||||
|
System.out.println("INFO: Case finished successfully for " + bean.getName());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import java.lang.management.MemoryPoolMXBean;
|
||||||
|
import sun.hotspot.code.BlobType;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test UsageThresholdNotExceededTest
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build UsageThresholdNotExceededTest
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:-UseCodeCacheFlushing
|
||||||
|
* -XX:-MethodFlushing -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
|
* -XX:+SegmentedCodeCache -XX:CompileCommand=compileonly,null::*
|
||||||
|
* UsageThresholdNotExceededTest
|
||||||
|
* @summary verifying that usage threshold not exceeded while allocating less
|
||||||
|
* than usage threshold
|
||||||
|
*/
|
||||||
|
public class UsageThresholdNotExceededTest {
|
||||||
|
|
||||||
|
private final BlobType btype;
|
||||||
|
|
||||||
|
public UsageThresholdNotExceededTest(BlobType btype) {
|
||||||
|
this.btype = btype;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
for (BlobType btype : BlobType.getAvailable()) {
|
||||||
|
if (CodeCacheUtils.isCodeHeapPredictable(btype)) {
|
||||||
|
new UsageThresholdNotExceededTest(btype).runTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void runTest() {
|
||||||
|
MemoryPoolMXBean bean = btype.getMemoryPool();
|
||||||
|
long initialThresholdCount = bean.getUsageThresholdCount();
|
||||||
|
long initialUsage = bean.getUsage().getUsed();
|
||||||
|
bean.setUsageThreshold(initialUsage + 1 + CodeCacheUtils.MIN_ALLOCATION);
|
||||||
|
CodeCacheUtils.WB.allocateCodeBlob(CodeCacheUtils.MIN_ALLOCATION
|
||||||
|
- CodeCacheUtils.getHeaderSize(btype), btype.id);
|
||||||
|
// a gc cycle triggers usage threshold recalculation
|
||||||
|
CodeCacheUtils.WB.fullGC();
|
||||||
|
Asserts.assertEQ(bean.getUsageThresholdCount(), initialThresholdCount,
|
||||||
|
String.format("Usage threshold was hit: %d times for %s. "
|
||||||
|
+ "Threshold value: %d with current usage: %d",
|
||||||
|
bean.getUsageThresholdCount(), bean.getName(),
|
||||||
|
bean.getUsageThreshold(), bean.getUsage().getUsed()));
|
||||||
|
|
||||||
|
System.out.println("INFO: Case finished successfully for "
|
||||||
|
+ bean.getName());
|
||||||
|
}
|
||||||
|
}
|
|
@ -127,10 +127,7 @@ public class TestRTMAbortRatio extends CommandLineOptionTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getMethodsToCompileNames() {
|
public String[] getMethodsToCompileNames() {
|
||||||
return new String[] {
|
return new String[] { getMethodWithLockName() };
|
||||||
getMethodWithLockName(),
|
|
||||||
Unsafe.class.getName() + "::addressSize"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void lock(boolean abort) {
|
public void lock(boolean abort) {
|
||||||
|
@ -148,10 +145,12 @@ public class TestRTMAbortRatio extends CommandLineOptionTest {
|
||||||
public static void main(String args[]) throws Throwable {
|
public static void main(String args[]) throws Throwable {
|
||||||
Asserts.assertGTE(args.length, 1, "One argument required.");
|
Asserts.assertGTE(args.length, 1, "One argument required.");
|
||||||
Test t = new Test();
|
Test t = new Test();
|
||||||
if (Boolean.valueOf(args[0])) {
|
boolean shouldBeInflated = Boolean.valueOf(args[0]);
|
||||||
|
if (shouldBeInflated) {
|
||||||
AbortProvoker.inflateMonitor(t.monitor);
|
AbortProvoker.inflateMonitor(t.monitor);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) {
|
for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) {
|
||||||
|
AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
|
||||||
t.lock(i >= Test.WARMUP_ITERATIONS);
|
t.lock(i >= Test.WARMUP_ITERATIONS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,10 +157,7 @@ public class TestRTMAfterNonRTMDeopt extends CommandLineOptionTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getMethodsToCompileNames() {
|
public String[] getMethodsToCompileNames() {
|
||||||
return new String[] {
|
return new String[] { getMethodWithLockName() };
|
||||||
getMethodWithLockName(),
|
|
||||||
sun.misc.Unsafe.class.getName() + "::forceAbort"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void forceAbort(int a[], boolean abort) {
|
public void forceAbort(int a[], boolean abort) {
|
||||||
|
@ -183,13 +180,15 @@ public class TestRTMAfterNonRTMDeopt extends CommandLineOptionTest {
|
||||||
public static void main(String args[]) throws Throwable {
|
public static void main(String args[]) throws Throwable {
|
||||||
Test t = new Test();
|
Test t = new Test();
|
||||||
|
|
||||||
if (Boolean.valueOf(args[0])) {
|
boolean shouldBeInflated = Boolean.valueOf(args[0]);
|
||||||
|
if (shouldBeInflated) {
|
||||||
AbortProvoker.inflateMonitor(t.monitor);
|
AbortProvoker.inflateMonitor(t.monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
int tmp[] = new int[1];
|
int tmp[] = new int[1];
|
||||||
|
|
||||||
for (int i = 0; i < Test.ITERATIONS; i++ ) {
|
for (int i = 0; i < Test.ITERATIONS; i++ ) {
|
||||||
|
AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
|
||||||
if (i == Test.RANGE_CHECK_AT) {
|
if (i == Test.RANGE_CHECK_AT) {
|
||||||
t.forceAbort(new int[0], false);
|
t.forceAbort(new int[0], false);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -130,10 +130,7 @@ public class TestRTMDeoptOnLowAbortRatio extends CommandLineOptionTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getMethodsToCompileNames() {
|
public String[] getMethodsToCompileNames() {
|
||||||
return new String[] {
|
return new String[] { getMethodWithLockName() };
|
||||||
getMethodWithLockName(),
|
|
||||||
sun.misc.Unsafe.class.getName() + "::addressSize"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void forceAbort(boolean abort) {
|
public void forceAbort(boolean abort) {
|
||||||
|
@ -151,11 +148,12 @@ public class TestRTMDeoptOnLowAbortRatio extends CommandLineOptionTest {
|
||||||
public static void main(String args[]) throws Throwable {
|
public static void main(String args[]) throws Throwable {
|
||||||
Asserts.assertGTE(args.length, 1, "One argument required.");
|
Asserts.assertGTE(args.length, 1, "One argument required.");
|
||||||
Test t = new Test();
|
Test t = new Test();
|
||||||
|
boolean shouldBeInflated = Boolean.valueOf(args[0]);
|
||||||
if (Boolean.valueOf(args[0])) {
|
if (shouldBeInflated) {
|
||||||
AbortProvoker.inflateMonitor(t.monitor);
|
AbortProvoker.inflateMonitor(t.monitor);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
|
for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
|
||||||
|
AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
|
||||||
t.forceAbort(
|
t.forceAbort(
|
||||||
i == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD);
|
i == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD);
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,10 +143,7 @@ public class TestRTMLockingThreshold extends CommandLineOptionTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getMethodsToCompileNames() {
|
public String[] getMethodsToCompileNames() {
|
||||||
return new String[] {
|
return new String[] { getMethodWithLockName() };
|
||||||
getMethodWithLockName(),
|
|
||||||
sun.misc.Unsafe.class.getName() + "::addressSize"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void lock(boolean abort) {
|
public void lock(boolean abort) {
|
||||||
|
@ -164,11 +161,12 @@ public class TestRTMLockingThreshold extends CommandLineOptionTest {
|
||||||
public static void main(String args[]) throws Throwable {
|
public static void main(String args[]) throws Throwable {
|
||||||
Asserts.assertGTE(args.length, 1, "One argument required.");
|
Asserts.assertGTE(args.length, 1, "One argument required.");
|
||||||
Test t = new Test();
|
Test t = new Test();
|
||||||
|
boolean shouldBeInflated = Boolean.valueOf(args[0]);
|
||||||
if (Boolean.valueOf(args[0])) {
|
if (shouldBeInflated) {
|
||||||
AbortProvoker.inflateMonitor(t.monitor);
|
AbortProvoker.inflateMonitor(t.monitor);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) {
|
for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) {
|
||||||
|
AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
|
||||||
t.lock(i % 2 == 1);
|
t.lock(i % 2 == 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,9 +117,7 @@ public class TestRTMTotalCountIncrRate extends CommandLineOptionTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getMethodsToCompileNames() {
|
public String[] getMethodsToCompileNames() {
|
||||||
return new String[] {
|
return new String[] { getMethodWithLockName() };
|
||||||
getMethodWithLockName()
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void lock() {
|
public void lock() {
|
||||||
|
@ -135,11 +133,13 @@ public class TestRTMTotalCountIncrRate extends CommandLineOptionTest {
|
||||||
public static void main(String args[]) throws Throwable {
|
public static void main(String args[]) throws Throwable {
|
||||||
Asserts.assertGTE(args.length, 1, "One argument required.");
|
Asserts.assertGTE(args.length, 1, "One argument required.");
|
||||||
Test test = new Test();
|
Test test = new Test();
|
||||||
|
boolean shouldBeInflated = Boolean.valueOf(args[0]);
|
||||||
if (Boolean.valueOf(args[0])) {
|
if (shouldBeInflated) {
|
||||||
AbortProvoker.inflateMonitor(test.monitor);
|
AbortProvoker.inflateMonitor(test.monitor);
|
||||||
}
|
}
|
||||||
for (long i = 0L; i < Test.TOTAL_ITERATIONS; i++) {
|
for (long i = 0L; i < Test.TOTAL_ITERATIONS; i++) {
|
||||||
|
AbortProvoker.verifyMonitorState(test.monitor,
|
||||||
|
shouldBeInflated);
|
||||||
test.lock();
|
test.lock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ import rtm.predicate.SupportedVM;
|
||||||
* Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times before
|
* Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times before
|
||||||
* lock inflation and the same amount of times after inflation.
|
* lock inflation and the same amount of times after inflation.
|
||||||
* As a result total locks count should be equal to
|
* As a result total locks count should be equal to
|
||||||
* {@code 2*AbortProvoker.DEFAULT_ITERATIONS}.
|
* {@code 2 * AbortProvoker.DEFAULT_ITERATIONS}.
|
||||||
* It is a pretty strict assertion which could fail if some retriable abort
|
* It is a pretty strict assertion which could fail if some retriable abort
|
||||||
* happened: it could be {@code AbortType.RETRIABLE} or
|
* happened: it could be {@code AbortType.RETRIABLE} or
|
||||||
* {@code AbortType.MEM_CONFLICT}, but unfortunately abort can has both these
|
* {@code AbortType.MEM_CONFLICT}, but unfortunately abort can has both these
|
||||||
|
@ -101,7 +101,6 @@ public class TestUseRTMAfterLockInflation extends CommandLineOptionTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Test {
|
public static class Test {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Usage:
|
* Usage:
|
||||||
* Test <provoker type>
|
* Test <provoker type>
|
||||||
|
@ -113,10 +112,12 @@ public class TestUseRTMAfterLockInflation extends CommandLineOptionTest {
|
||||||
AbortProvoker provoker
|
AbortProvoker provoker
|
||||||
= AbortType.lookup(Integer.valueOf(args[0])).provoker();
|
= AbortType.lookup(Integer.valueOf(args[0])).provoker();
|
||||||
for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
|
for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
|
||||||
|
AbortProvoker.verifyMonitorState(provoker, false /*deflated*/);
|
||||||
provoker.forceAbort();
|
provoker.forceAbort();
|
||||||
}
|
}
|
||||||
provoker.inflateMonitor();
|
provoker.inflateMonitor();
|
||||||
for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
|
for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
|
||||||
|
AbortProvoker.verifyMonitorState(provoker, true /*inflated*/);
|
||||||
provoker.forceAbort();
|
provoker.forceAbort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
61
hotspot/test/compiler/testlibrary/CompilerUtils.java
Normal file
61
hotspot/test/compiler/testlibrary/CompilerUtils.java
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import com.oracle.java.testlibrary.Platform;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
|
||||||
|
public class CompilerUtils {
|
||||||
|
|
||||||
|
private CompilerUtils() {
|
||||||
|
// to prevent from instantiation
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns available compilation levels
|
||||||
|
*
|
||||||
|
* @return int array with compilation levels
|
||||||
|
*/
|
||||||
|
public static int[] getAvailableCompilationLevels() {
|
||||||
|
if (!WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompiler")) {
|
||||||
|
return new int[0];
|
||||||
|
}
|
||||||
|
if (WhiteBox.getWhiteBox().getBooleanVMFlag("TieredCompilation")) {
|
||||||
|
Long flagValue = WhiteBox.getWhiteBox()
|
||||||
|
.getIntxVMFlag("TieredStopAtLevel");
|
||||||
|
int maxLevel = flagValue.intValue();
|
||||||
|
Asserts.assertEQ(new Long(maxLevel), flagValue,
|
||||||
|
"TieredStopAtLevel has value out of int capacity");
|
||||||
|
return IntStream.rangeClosed(1, maxLevel).toArray();
|
||||||
|
} else {
|
||||||
|
if (Platform.isServer()) {
|
||||||
|
return new int[]{4};
|
||||||
|
}
|
||||||
|
if (Platform.isClient() || Platform.isMinimal()) {
|
||||||
|
return new int[]{1};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new int[0];
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,8 +29,7 @@ import java.util.concurrent.BrokenBarrierException;
|
||||||
import java.util.concurrent.CyclicBarrier;
|
import java.util.concurrent.CyclicBarrier;
|
||||||
|
|
||||||
import com.oracle.java.testlibrary.Asserts;
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
import com.oracle.java.testlibrary.Utils;
|
import sun.hotspot.WhiteBox;
|
||||||
import sun.misc.Unsafe;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for different transactional execution abortion
|
* Base class for different transactional execution abortion
|
||||||
|
@ -38,6 +37,9 @@ import sun.misc.Unsafe;
|
||||||
*/
|
*/
|
||||||
public abstract class AbortProvoker implements CompilableTest {
|
public abstract class AbortProvoker implements CompilableTest {
|
||||||
public static final long DEFAULT_ITERATIONS = 10000L;
|
public static final long DEFAULT_ITERATIONS = 10000L;
|
||||||
|
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static int sharedState = 0;
|
||||||
/**
|
/**
|
||||||
* Inflates monitor associated with object {@code monitor}.
|
* Inflates monitor associated with object {@code monitor}.
|
||||||
* Inflation is forced by entering the same monitor from
|
* Inflation is forced by entering the same monitor from
|
||||||
|
@ -48,36 +50,76 @@ public abstract class AbortProvoker implements CompilableTest {
|
||||||
* @throws Exception if something went wrong.
|
* @throws Exception if something went wrong.
|
||||||
*/
|
*/
|
||||||
public static Object inflateMonitor(Object monitor) throws Exception {
|
public static Object inflateMonitor(Object monitor) throws Exception {
|
||||||
Unsafe unsafe = Utils.getUnsafe();
|
|
||||||
CyclicBarrier barrier = new CyclicBarrier(2);
|
CyclicBarrier barrier = new CyclicBarrier(2);
|
||||||
|
|
||||||
Runnable inflatingRunnable = () -> {
|
Runnable inflatingRunnable = () -> {
|
||||||
unsafe.monitorEnter(monitor);
|
synchronized (monitor) {
|
||||||
try {
|
try {
|
||||||
barrier.await();
|
barrier.await();
|
||||||
barrier.await();
|
} catch (BrokenBarrierException | InterruptedException e) {
|
||||||
} catch (InterruptedException | BrokenBarrierException e) {
|
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
"Synchronization issue occurred.", e);
|
"Synchronization issue occurred.", e);
|
||||||
} finally {
|
}
|
||||||
unsafe.monitorExit(monitor);
|
try {
|
||||||
|
monitor.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new AssertionError("The thread waiting on an"
|
||||||
|
+ " inflated monitor was interrupted, thus test"
|
||||||
|
+ " results may be incorrect.", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Thread t = new Thread(inflatingRunnable);
|
Thread t = new Thread(inflatingRunnable);
|
||||||
|
t.setDaemon(true);
|
||||||
t.start();
|
t.start();
|
||||||
// Wait until thread t enters the monitor.
|
// Wait until thread t enters the monitor.
|
||||||
barrier.await();
|
barrier.await();
|
||||||
// At this point monitor will be owned by thread t,
|
synchronized (monitor) {
|
||||||
// so our attempt to enter the same monitor will force
|
// At this point thread t is already waiting on the monitor.
|
||||||
// monitor inflation.
|
// Modifying static field just to avoid lock's elimination.
|
||||||
Asserts.assertFalse(unsafe.tryMonitorEnter(monitor),
|
sharedState++;
|
||||||
"Not supposed to enter the monitor first");
|
}
|
||||||
barrier.await();
|
verifyMonitorState(monitor, true /* inflated */);
|
||||||
t.join();
|
|
||||||
return monitor;
|
return monitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that {@code monitor} is a stack-lock or inflated lock depending
|
||||||
|
* on {@code shouldBeInflated} value. If {@code monitor} is inflated while
|
||||||
|
* it is expected that it should be a stack-lock, then this method attempts
|
||||||
|
* to deflate it by forcing a safepoint and then verifies the state once
|
||||||
|
* again.
|
||||||
|
*
|
||||||
|
* @param monitor monitor to be verified.
|
||||||
|
* @param shouldBeInflated flag indicating whether or not monitor is
|
||||||
|
* expected to be inflated.
|
||||||
|
* @throws RuntimeException if the {@code monitor} in a wrong state.
|
||||||
|
*/
|
||||||
|
public static void verifyMonitorState(Object monitor,
|
||||||
|
boolean shouldBeInflated) {
|
||||||
|
if (!shouldBeInflated && WHITE_BOX.isMonitorInflated(monitor)) {
|
||||||
|
WHITE_BOX.forceSafepoint();
|
||||||
|
}
|
||||||
|
Asserts.assertEQ(WHITE_BOX.isMonitorInflated(monitor), shouldBeInflated,
|
||||||
|
"Monitor in a wrong state.");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Verifies that monitor used by the {@code provoker} is a stack-lock or
|
||||||
|
* inflated lock depending on {@code shouldBeInflated} value. If such
|
||||||
|
* monitor is inflated while it is expected that it should be a stack-lock,
|
||||||
|
* then this method attempts to deflate it by forcing a safepoint and then
|
||||||
|
* verifies the state once again.
|
||||||
|
*
|
||||||
|
* @param provoker AbortProvoker whose monitor's state should be verified.
|
||||||
|
* @param shouldBeInflated flag indicating whether or not monitor is
|
||||||
|
* expected to be inflated.
|
||||||
|
* @throws RuntimeException if the {@code monitor} in a wrong state.
|
||||||
|
*/
|
||||||
|
public static void verifyMonitorState(AbortProvoker provoker,
|
||||||
|
boolean shouldBeInflated) {
|
||||||
|
verifyMonitorState(provoker.monitor, shouldBeInflated);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get instance of specified AbortProvoker, inflate associated monitor
|
* Get instance of specified AbortProvoker, inflate associated monitor
|
||||||
|
@ -120,6 +162,7 @@ public abstract class AbortProvoker implements CompilableTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (long i = 0; i < iterations; i++) {
|
for (long i = 0; i < iterations; i++) {
|
||||||
|
AbortProvoker.verifyMonitorState(provoker, monitorShouldBeInflated);
|
||||||
provoker.forceAbort();
|
provoker.forceAbort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ public class BusyLock implements CompilableTest, Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void test() {
|
public void syncAndTest() {
|
||||||
try {
|
try {
|
||||||
barrier.await();
|
barrier.await();
|
||||||
// wait until monitor is locked by a ::run method
|
// wait until monitor is locked by a ::run method
|
||||||
|
@ -85,6 +85,10 @@ public class BusyLock implements CompilableTest, Runnable {
|
||||||
} catch (InterruptedException | BrokenBarrierException e) {
|
} catch (InterruptedException | BrokenBarrierException e) {
|
||||||
throw new RuntimeException("Synchronization error happened.", e);
|
throw new RuntimeException("Synchronization error happened.", e);
|
||||||
}
|
}
|
||||||
|
test();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test() {
|
||||||
synchronized(monitor) {
|
synchronized(monitor) {
|
||||||
BusyLock.field++;
|
BusyLock.field++;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +134,7 @@ public class BusyLock implements CompilableTest, Runnable {
|
||||||
|
|
||||||
Thread t = new Thread(busyLock);
|
Thread t = new Thread(busyLock);
|
||||||
t.start();
|
t.start();
|
||||||
busyLock.test();
|
busyLock.syncAndTest();
|
||||||
t.join();
|
t.join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,11 +69,6 @@ class MemoryConflictProvoker extends AbortProvoker {
|
||||||
* Accesses and modifies memory region from within the transaction.
|
* Accesses and modifies memory region from within the transaction.
|
||||||
*/
|
*/
|
||||||
public void transactionalRegion() {
|
public void transactionalRegion() {
|
||||||
try {
|
|
||||||
barrier.await();
|
|
||||||
} catch (InterruptedException | BrokenBarrierException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < MemoryConflictProvoker.INNER_ITERATIONS; i++) {
|
for (int i = 0; i < MemoryConflictProvoker.INNER_ITERATIONS; i++) {
|
||||||
synchronized(monitor) {
|
synchronized(monitor) {
|
||||||
MemoryConflictProvoker.field--;
|
MemoryConflictProvoker.field--;
|
||||||
|
@ -86,6 +81,11 @@ class MemoryConflictProvoker extends AbortProvoker {
|
||||||
try {
|
try {
|
||||||
Thread t = new Thread(conflictingThread);
|
Thread t = new Thread(conflictingThread);
|
||||||
t.start();
|
t.start();
|
||||||
|
try {
|
||||||
|
barrier.await();
|
||||||
|
} catch (InterruptedException | BrokenBarrierException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
transactionalRegion();
|
transactionalRegion();
|
||||||
t.join();
|
t.join();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -240,7 +240,8 @@ public class RTMTestBase {
|
||||||
Collections.addAll(finalVMOpts, "-Xcomp", "-server",
|
Collections.addAll(finalVMOpts, "-Xcomp", "-server",
|
||||||
"-XX:-TieredCompilation", "-XX:+UseRTMLocking",
|
"-XX:-TieredCompilation", "-XX:+UseRTMLocking",
|
||||||
CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS,
|
CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS,
|
||||||
CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS);
|
CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
|
||||||
|
"-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI");
|
||||||
|
|
||||||
if (test != null) {
|
if (test != null) {
|
||||||
for (String method : test.getMethodsToCompileNames()) {
|
for (String method : test.getMethodsToCompileNames()) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ import java.security.SecureClassLoader;
|
||||||
public class ByteCodeLoader extends SecureClassLoader {
|
public class ByteCodeLoader extends SecureClassLoader {
|
||||||
private final String className;
|
private final String className;
|
||||||
private final byte[] byteCode;
|
private final byte[] byteCode;
|
||||||
|
private volatile Class<?> holder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@code ByteCodeLoader} ready to load a class with the
|
* Creates a new {@code ByteCodeLoader} ready to load a class with the
|
||||||
|
@ -50,6 +51,21 @@ public class ByteCodeLoader extends SecureClassLoader {
|
||||||
this.byteCode = byteCode;
|
this.byteCode = byteCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||||
|
if (!name.equals(className)) {
|
||||||
|
return super.loadClass(name);
|
||||||
|
}
|
||||||
|
if (holder == null) {
|
||||||
|
synchronized(this) {
|
||||||
|
if (holder == null) {
|
||||||
|
holder = findClass(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return holder;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||||
if (!name.equals(className)) {
|
if (!name.equals(className)) {
|
||||||
|
|
|
@ -54,8 +54,10 @@ public class InfiniteLoop implements Runnable {
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
target.run();
|
target.run();
|
||||||
|
if (mills > 0) {
|
||||||
Thread.sleep(mills);
|
Thread.sleep(mills);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
throw new Error(e);
|
throw new Error(e);
|
||||||
|
|
|
@ -34,6 +34,7 @@ public class Platform {
|
||||||
private static final String osArch = System.getProperty("os.arch");
|
private static final String osArch = System.getProperty("os.arch");
|
||||||
private static final String vmName = System.getProperty("java.vm.name");
|
private static final String vmName = System.getProperty("java.vm.name");
|
||||||
private static final String userName = System.getProperty("user.name");
|
private static final String userName = System.getProperty("user.name");
|
||||||
|
private static final String compiler = System.getProperty("sun.management.compiler");
|
||||||
|
|
||||||
public static boolean isClient() {
|
public static boolean isClient() {
|
||||||
return vmName.endsWith(" Client VM");
|
return vmName.endsWith(" Client VM");
|
||||||
|
@ -55,6 +56,10 @@ public class Platform {
|
||||||
return vmName.contains("Embedded");
|
return vmName.contains("Embedded");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isTieredSupported() {
|
||||||
|
return compiler.contains("Tiered Compilers");
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean is32bit() {
|
public static boolean is32bit() {
|
||||||
return dataModel.equals("32");
|
return dataModel.equals("32");
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.function.BooleanSupplier;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
@ -305,25 +306,6 @@ public final class Utils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns file content as a list of strings
|
|
||||||
*
|
|
||||||
* @param file File to operate on
|
|
||||||
* @return List of strings
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public static List<String> fileAsList(File file) throws IOException {
|
|
||||||
assertTrue(file.exists() && file.isFile(),
|
|
||||||
file.getAbsolutePath() + " does not exist or not a file");
|
|
||||||
List<String> output = new ArrayList<>();
|
|
||||||
try (BufferedReader reader = new BufferedReader(new FileReader(file.getAbsolutePath()))) {
|
|
||||||
while (reader.ready()) {
|
|
||||||
output.add(reader.readLine().replace(NEW_LINE, ""));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the contents of the named file as a single String,
|
* Return the contents of the named file as a single String,
|
||||||
* or null if not found.
|
* or null if not found.
|
||||||
|
@ -395,6 +377,52 @@ public final class Utils {
|
||||||
return RANDOM_GENERATOR;
|
return RANDOM_GENERATOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for condition to be true
|
||||||
|
*
|
||||||
|
* @param condition, a condition to wait for
|
||||||
|
*/
|
||||||
|
public static final void waitForCondition(BooleanSupplier condition) {
|
||||||
|
waitForCondition(condition, -1L, 100L);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait until timeout for condition to be true
|
||||||
|
*
|
||||||
|
* @param condition, a condition to wait for
|
||||||
|
* @param timeout a time in milliseconds to wait for condition to be true
|
||||||
|
* specifying -1 will wait forever
|
||||||
|
* @return condition value, to determine if wait was successfull
|
||||||
|
*/
|
||||||
|
public static final boolean waitForCondition(BooleanSupplier condition,
|
||||||
|
long timeout) {
|
||||||
|
return waitForCondition(condition, timeout, 100L);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait until timeout for condition to be true for specified time
|
||||||
|
*
|
||||||
|
* @param condition, a condition to wait for
|
||||||
|
* @param timeout a time in milliseconds to wait for condition to be true,
|
||||||
|
* specifying -1 will wait forever
|
||||||
|
* @param sleepTime a time to sleep value in milliseconds
|
||||||
|
* @return condition value, to determine if wait was successfull
|
||||||
|
*/
|
||||||
|
public static final boolean waitForCondition(BooleanSupplier condition,
|
||||||
|
long timeout, long sleepTime) {
|
||||||
|
long startTime = System.currentTimeMillis();
|
||||||
|
while (!(condition.getAsBoolean() || (timeout != -1L
|
||||||
|
&& ((System.currentTimeMillis() - startTime) > timeout)))) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(sleepTime);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return condition.getAsBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adjusts the provided timeout value for the TIMEOUT_FACTOR
|
* Adjusts the provided timeout value for the TIMEOUT_FACTOR
|
||||||
* @param tOut the timeout value to be adjusted
|
* @param tOut the timeout value to be adjusted
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
package com.oracle.java.testlibrary.dtrace;
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.OutputAnalyzer;
|
||||||
|
|
||||||
|
public interface DtraceResultsAnalyzer {
|
||||||
|
public void analyze(OutputAnalyzer oa, String logFilePath);
|
||||||
|
}
|
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
package com.oracle.java.testlibrary.dtrace;
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import com.oracle.java.testlibrary.OutputAnalyzer;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DtraceRunner {
|
||||||
|
|
||||||
|
private static final String DTRACE_DEFAULT_PATH = "/usr/sbin/dtrace";
|
||||||
|
private static final String DTRACE_PATH_PROPERTY
|
||||||
|
= "com.oracle.test.dtrace.path";
|
||||||
|
private static final String OUTPUT_FILE_DTRACE_OPTION = "o";
|
||||||
|
private static final String RUN_COMMAND_DTRACE_OPTION = "c";
|
||||||
|
private static final String RUN_SCRIPT_DTRACE_OPTION = "s";
|
||||||
|
private static final String ALLOW_ZERO_PROBE_DESCRIPTION_DTRACE_OPTION = "Z";
|
||||||
|
private static final String DTRACE_OPTION_PREFIX = "-";
|
||||||
|
public static final String PERMIT_DESTRUCTIVE_ACTIONS_DTRACE_OPTION = "w";
|
||||||
|
public static final String DTRACE_OUT_LOG = "dtrace.out";
|
||||||
|
|
||||||
|
private final String dtraceExecutable;
|
||||||
|
|
||||||
|
public DtraceRunner() {
|
||||||
|
dtraceExecutable = getDtracePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getLaunchCmd(String java, String javaOpts,
|
||||||
|
String execClass, String testArgs, String dtraceScript,
|
||||||
|
String dtraceAddOpts) {
|
||||||
|
Asserts.assertTrue(!java.matches("\\s"), "Current dtrace implementation"
|
||||||
|
+ " can't handle whitespaces in application path");
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
result.add(dtraceExecutable);
|
||||||
|
result.add(DTRACE_OPTION_PREFIX + System.getProperty("sun.arch.data.model"));
|
||||||
|
result.add(DTRACE_OPTION_PREFIX
|
||||||
|
+ ALLOW_ZERO_PROBE_DESCRIPTION_DTRACE_OPTION
|
||||||
|
+ ((dtraceAddOpts == null) ? "" : dtraceAddOpts)
|
||||||
|
+ RUN_SCRIPT_DTRACE_OPTION); // run_script should be last one
|
||||||
|
result.add(dtraceScript);
|
||||||
|
result.add(DTRACE_OPTION_PREFIX + OUTPUT_FILE_DTRACE_OPTION);
|
||||||
|
result.add(DTRACE_OUT_LOG);
|
||||||
|
result.add(DTRACE_OPTION_PREFIX + RUN_COMMAND_DTRACE_OPTION);
|
||||||
|
result.add(java + " " + javaOpts + " " + execClass + " " + testArgs);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void backupLogFile(File file) {
|
||||||
|
if (file.exists()) {
|
||||||
|
file.renameTo(new File(file.getPath() + ".bak"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runDtrace(String java, String javaOpts, String execClass,
|
||||||
|
String testArgs, String dtraceScript, String dtraceAddOpts,
|
||||||
|
DtraceResultsAnalyzer analyzer) {
|
||||||
|
backupLogFile(new File(DTRACE_OUT_LOG));
|
||||||
|
ProcessBuilder pbuilder = new ProcessBuilder(
|
||||||
|
getLaunchCmd(java, javaOpts, execClass, testArgs,
|
||||||
|
dtraceScript, dtraceAddOpts));
|
||||||
|
OutputAnalyzer oa;
|
||||||
|
try {
|
||||||
|
oa = new OutputAnalyzer(pbuilder.start());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new Error("TESTBUG: Can't start process", e);
|
||||||
|
}
|
||||||
|
analyzer.analyze(oa, DTRACE_OUT_LOG);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean dtraceAvailable() {
|
||||||
|
String path = getDtracePath();
|
||||||
|
if (path == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// now we'll launch dtrace to trace itself just to be sure it works
|
||||||
|
// and have all additional previleges set
|
||||||
|
ProcessBuilder pbuilder = new ProcessBuilder(path, path);
|
||||||
|
try {
|
||||||
|
OutputAnalyzer oa = new OutputAnalyzer(pbuilder.start());
|
||||||
|
if (oa.getExitValue() != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new Error("Couldn't launch dtrace", e);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getDtracePath() {
|
||||||
|
String propPath = System.getProperty(DTRACE_PATH_PROPERTY);
|
||||||
|
if (propPath != null && new File(propPath).exists()) {
|
||||||
|
return propPath;
|
||||||
|
} else if (new File(DTRACE_DEFAULT_PATH).exists()) {
|
||||||
|
return DTRACE_DEFAULT_PATH;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +0,0 @@
|
||||||
public class Bar {
|
|
||||||
private static void staticMethod() { }
|
|
||||||
public void method() { }
|
|
||||||
protected Bar() { }
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2013, 2014, 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 8012447
|
|
||||||
* @library /testlibrary /../../test/lib /testlibrary/ctw/src
|
|
||||||
* @build ClassFileInstaller sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar
|
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
|
|
||||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
|
||||||
* @run main ClassesDirTest prepare
|
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld classes
|
|
||||||
* @run main ClassesDirTest check ctw.log
|
|
||||||
* @summary testing of CompileTheWorld :: classes in directory
|
|
||||||
* @author igor.ignatyev@oracle.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
|
|
||||||
public class ClassesDirTest extends CtwTest {
|
|
||||||
private static final String[] SHOULD_CONTAIN
|
|
||||||
= {"# dir: classes", "Done (2 classes, 6 methods, "};
|
|
||||||
|
|
||||||
private ClassesDirTest() {
|
|
||||||
super(SHOULD_CONTAIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
new ClassesDirTest().run(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void prepare() throws Exception {
|
|
||||||
String path = "classes";
|
|
||||||
Files.createDirectory(Paths.get(path));
|
|
||||||
Files.move(Paths.get("Foo.class"), Paths.get(path, "Foo.class"),
|
|
||||||
StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
Files.move(Paths.get("Bar.class"), Paths.get(path, "Bar.class"),
|
|
||||||
StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2013, 2014, 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 8012447
|
|
||||||
* @library /testlibrary /../../test/lib /testlibrary/ctw/src
|
|
||||||
* @build ClassFileInstaller sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar
|
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
|
|
||||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
|
||||||
* @run main ClassesListTest prepare
|
|
||||||
* @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld classes.lst
|
|
||||||
* @run main ClassesListTest check ctw.log
|
|
||||||
* @summary testing of CompileTheWorld :: list of classes in file
|
|
||||||
* @author igor.ignatyev@oracle.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
|
|
||||||
public class ClassesListTest extends CtwTest {
|
|
||||||
private static final String[] SHOULD_CONTAIN
|
|
||||||
= {"# list: classes.lst", "Done (4 classes, "};
|
|
||||||
|
|
||||||
private ClassesListTest() {
|
|
||||||
super(SHOULD_CONTAIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
new ClassesListTest().run(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void prepare() throws Exception {
|
|
||||||
String path = "classes.lst";
|
|
||||||
Files.copy(Paths.get(System.getProperty("test.src"), path),
|
|
||||||
Paths.get(path), StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,118 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
|
|
||||||
import com.oracle.java.testlibrary.JDKToolFinder;
|
|
||||||
import com.oracle.java.testlibrary.OutputAnalyzer;
|
|
||||||
|
|
||||||
public abstract class CtwTest {
|
|
||||||
protected final String[] shouldContain;
|
|
||||||
protected CtwTest(String[] shouldContain) {
|
|
||||||
this.shouldContain = shouldContain;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run(String[] args) throws Exception {
|
|
||||||
if (args.length == 0) {
|
|
||||||
throw new Error("args is empty");
|
|
||||||
}
|
|
||||||
switch (args[0]) {
|
|
||||||
case "prepare":
|
|
||||||
prepare();
|
|
||||||
break;
|
|
||||||
case "check":
|
|
||||||
check(args);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error("unregonized action -- " + args[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void prepare() throws Exception { }
|
|
||||||
|
|
||||||
protected void check(String[] args) throws Exception {
|
|
||||||
if (args.length < 2) {
|
|
||||||
throw new Error("logfile isn't specified");
|
|
||||||
}
|
|
||||||
String logfile = args[1];
|
|
||||||
try (BufferedReader r = Files.newBufferedReader(Paths.get(logfile),
|
|
||||||
Charset.defaultCharset())) {
|
|
||||||
OutputAnalyzer output = readOutput(r);
|
|
||||||
for (String test : shouldContain) {
|
|
||||||
output.shouldContain(test);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static OutputAnalyzer readOutput(BufferedReader reader)
|
|
||||||
throws IOException {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
String eol = String.format("%n");
|
|
||||||
String line;
|
|
||||||
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
builder.append(line);
|
|
||||||
builder.append(eol);
|
|
||||||
}
|
|
||||||
return new OutputAnalyzer(builder.toString(), "");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void dump(OutputAnalyzer output, String name) {
|
|
||||||
try (Writer w = new FileWriter(name + ".out")) {
|
|
||||||
String s = output.getStdout();
|
|
||||||
w.write(s, s.length(), 0);
|
|
||||||
} catch (IOException io) {
|
|
||||||
io.printStackTrace();
|
|
||||||
}
|
|
||||||
try (Writer w = new FileWriter(name + ".err")) {
|
|
||||||
String s = output.getStderr();
|
|
||||||
w.write(s, s.length(), 0);
|
|
||||||
} catch (IOException io) {
|
|
||||||
io.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ProcessBuilder createJarProcessBuilder(String... command)
|
|
||||||
throws Exception {
|
|
||||||
String javapath = JDKToolFinder.getJDKTool("jar");
|
|
||||||
|
|
||||||
ArrayList<String> args = new ArrayList<>();
|
|
||||||
args.add(javapath);
|
|
||||||
Collections.addAll(args, command);
|
|
||||||
|
|
||||||
return new ProcessBuilder(args.toArray(new String[args.size()]));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
public class Foo {
|
|
||||||
private static void staticMethod() { }
|
|
||||||
public void method() { }
|
|
||||||
protected Foo() { }
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2013, 2014, 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 8012447
|
|
||||||
* @library /testlibrary /../../test/lib /testlibrary/ctw/src
|
|
||||||
* @build ClassFileInstaller com.oracle.java.testlibrary.* sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar
|
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
|
|
||||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
|
||||||
* @run main JarDirTest prepare
|
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld jars/*
|
|
||||||
* @run main JarDirTest check ctw.log
|
|
||||||
* @summary testing of CompileTheWorld :: jars in directory
|
|
||||||
* @author igor.ignatyev@oracle.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
|
|
||||||
import com.oracle.java.testlibrary.OutputAnalyzer;
|
|
||||||
|
|
||||||
public class JarDirTest extends CtwTest {
|
|
||||||
private static final String[] SHOULD_CONTAIN
|
|
||||||
= {"# jar_in_dir: jars",
|
|
||||||
"# jar: jars" + File.separator +"foo.jar",
|
|
||||||
"# jar: jars" + File.separator +"bar.jar",
|
|
||||||
"Done (4 classes, 12 methods, "};
|
|
||||||
|
|
||||||
private JarDirTest() {
|
|
||||||
super(SHOULD_CONTAIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
new JarDirTest().run(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void prepare() throws Exception {
|
|
||||||
String path = "jars";
|
|
||||||
Files.createDirectory(Paths.get(path));
|
|
||||||
|
|
||||||
ProcessBuilder pb = createJarProcessBuilder("cf", "jars/foo.jar",
|
|
||||||
"Foo.class", "Bar.class");
|
|
||||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
|
||||||
dump(output, "ctw-foo.jar");
|
|
||||||
output.shouldHaveExitValue(0);
|
|
||||||
|
|
||||||
pb = createJarProcessBuilder("cf", "jars/bar.jar", "Foo.class",
|
|
||||||
"Bar.class");
|
|
||||||
output = new OutputAnalyzer(pb.start());
|
|
||||||
dump(output, "ctw-bar.jar");
|
|
||||||
output.shouldHaveExitValue(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2013, 2014, 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 8012447
|
|
||||||
* @library /testlibrary /../../test/lib /testlibrary/ctw/src
|
|
||||||
* @build ClassFileInstaller com.oracle.java.testlibrary.* sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar
|
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
|
|
||||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
|
||||||
* @run main JarsTest prepare
|
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld foo.jar bar.jar
|
|
||||||
* @run main JarsTest check ctw.log
|
|
||||||
* @summary testing of CompileTheWorld :: jars
|
|
||||||
* @author igor.ignatyev@oracle.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
import com.oracle.java.testlibrary.OutputAnalyzer;
|
|
||||||
|
|
||||||
public class JarsTest extends CtwTest {
|
|
||||||
private static final String[] SHOULD_CONTAIN
|
|
||||||
= {"# jar: foo.jar", "# jar: bar.jar",
|
|
||||||
"Done (4 classes, 12 methods, "};
|
|
||||||
|
|
||||||
private JarsTest() {
|
|
||||||
super(SHOULD_CONTAIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
new JarsTest().run(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void prepare() throws Exception {
|
|
||||||
ProcessBuilder pb = createJarProcessBuilder("cf", "foo.jar",
|
|
||||||
"Foo.class", "Bar.class");
|
|
||||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
|
||||||
dump(output, "ctw-foo.jar");
|
|
||||||
output.shouldHaveExitValue(0);
|
|
||||||
|
|
||||||
pb = createJarProcessBuilder("cf", "bar.jar", "Foo.class", "Bar.class");
|
|
||||||
output = new OutputAnalyzer(pb.start());
|
|
||||||
dump(output, "ctw-bar.jar");
|
|
||||||
output.shouldHaveExitValue(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
java.lang.String
|
|
||||||
java.lang.Object
|
|
||||||
Foo
|
|
||||||
Bar
|
|
|
@ -48,7 +48,7 @@ public class TestMutuallyExclusivePlatformPredicates {
|
||||||
OS("isLinux", "isSolaris", "isWindows", "isOSX"),
|
OS("isLinux", "isSolaris", "isWindows", "isOSX"),
|
||||||
VM_TYPE("isClient", "isServer", "isGraal", "isMinimal"),
|
VM_TYPE("isClient", "isServer", "isGraal", "isMinimal"),
|
||||||
IGNORED("isEmbedded", "isDebugBuild", "shouldSAAttach",
|
IGNORED("isEmbedded", "isDebugBuild", "shouldSAAttach",
|
||||||
"canPtraceAttachLinux", "canAttachOSX");
|
"canPtraceAttachLinux", "canAttachOSX", "isTieredSupported");
|
||||||
|
|
||||||
public final List<String> methodNames;
|
public final List<String> methodNames;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
import com.oracle.java.testlibrary.Platform;
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @summary Verifies that Platform::isTieredSupported returns correct value.
|
||||||
|
* @library /testlibrary /../../test/lib
|
||||||
|
* @build TestPlatformIsTieredSupported
|
||||||
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
|
* -XX:+WhiteBoxAPI -XX:+TieredCompilation
|
||||||
|
* TestPlatformIsTieredSupported
|
||||||
|
*/
|
||||||
|
public class TestPlatformIsTieredSupported {
|
||||||
|
public static void main(String args[]) {
|
||||||
|
WhiteBox whiteBox = WhiteBox.getWhiteBox();
|
||||||
|
boolean tieredCompilation = whiteBox.getBooleanVMFlag(
|
||||||
|
"TieredCompilation");
|
||||||
|
Asserts.assertEQ(Platform.isTieredSupported(), tieredCompilation,
|
||||||
|
"Platform::isTieredSupported should report the same value as "
|
||||||
|
+ "TieredCompilation flag's value when "
|
||||||
|
+ "+TieredCompilation was explicitly passed to JVM.");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue