--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Thu Jan 08 17:45:10 2015 -0500
@@ -59,7 +59,7 @@
_has_nonstatic_fields = ik->has_nonstatic_fields();
_has_default_methods = ik->has_default_methods();
_nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
-
+ _has_injected_fields = -1;
_implementor = NULL; // we will fill these lazily
Thread *thread = Thread::current();
@@ -100,6 +100,7 @@
_nonstatic_field_size = -1;
_has_nonstatic_fields = false;
_nonstatic_fields = NULL;
+ _has_injected_fields = -1;
_loader = loader;
_protection_domain = protection_domain;
_is_shared = false;
@@ -500,6 +501,34 @@
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
//
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp Thu Jan 08 17:45:10 2015 -0500
@@ -64,6 +64,7 @@
ciConstantPoolCache* _field_cache; // cached map index->field
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:
// NULL: no implementor.
@@ -71,6 +72,9 @@
// Itsef: more than one implementors.
ciInstanceKlass* _implementor;
+ bool compute_injected_fields();
+ void compute_injected_fields_helper();
+
protected:
ciInstanceKlass(KlassHandle h_k);
ciInstanceKlass(ciSymbol* name, jobject loader, jobject protection_domain);
@@ -186,6 +190,14 @@
else
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)
ciField* nonstatic_field_at(int i) {
assert(_nonstatic_fields != NULL, "");
--- a/hotspot/src/share/vm/oops/fieldStreams.hpp Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/src/share/vm/oops/fieldStreams.hpp Thu Jan 08 17:45:10 2015 -0500
@@ -51,7 +51,7 @@
int init_generic_signature_start_slot() {
int length = _fields->length();
- int num_fields = 0;
+ int num_fields = _index;
int skipped_generic_signature_slots = 0;
FieldInfo* fi;
AccessFlags flags;
--- a/hotspot/src/share/vm/opto/c2_globals.hpp Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp Thu Jan 08 17:45:10 2015 -0500
@@ -669,6 +669,13 @@
product_pd(bool, TrapBasedRangeChecks, \
"Generate code for range checks that uses a cmp and trap " \
"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)
--- a/hotspot/src/share/vm/opto/c2compiler.cpp Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/src/share/vm/opto/c2compiler.cpp Thu Jan 08 17:45:10 2015 -0500
@@ -39,6 +39,9 @@
const char* C2Compiler::retry_no_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() {
// Check assumptions used while running ADLC
@@ -104,6 +107,10 @@
// Check result and retry if appropriate.
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())) {
assert(subsume_loads, "must make progress");
subsume_loads = false;
--- a/hotspot/src/share/vm/opto/c2compiler.hpp Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/src/share/vm/opto/c2compiler.hpp Thu Jan 08 17:45:10 2015 -0500
@@ -47,6 +47,7 @@
// sentinel value used to trigger backtracking in compile_method().
static const char* retry_no_subsuming_loads();
static const char* retry_no_escape_analysis();
+ static const char* retry_class_loading_during_parsing();
// Print compilation timers and statistics
void print_timers();
--- a/hotspot/src/share/vm/opto/callnode.cpp Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/src/share/vm/opto/callnode.cpp Thu Jan 08 17:45:10 2015 -0500
@@ -28,6 +28,7 @@
#include "opto/callGenerator.hpp"
#include "opto/callnode.hpp"
#include "opto/castnode.hpp"
+#include "opto/convertnode.hpp"
#include "opto/escape.hpp"
#include "opto/locknode.hpp"
#include "opto/machnode.hpp"
@@ -1818,7 +1819,10 @@
}
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_flags(Flag_is_macro);
C->add_macro_node(this);
@@ -1870,3 +1874,136 @@
st->print(" (%s%s)", _kind_names[_kind], _alloc_tightly_coupled ? ", tightly coupled allocation" : "");
}
#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;
+}
--- a/hotspot/src/share/vm/opto/callnode.hpp Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/src/share/vm/opto/callnode.hpp Thu Jan 08 17:45:10 2015 -0500
@@ -1070,8 +1070,8 @@
// What kind of arraycopy variant is this?
enum {
+ None, // not set yet
ArrayCopy, // System.arraycopy()
- ArrayCopyNoTest, // System.arraycopy(), all arguments validated
CloneBasic, // A clone that can be copied by 64 bit chunks
CloneOop, // An oop array clone
CopyOf, // Arrays.copyOf()
@@ -1095,6 +1095,8 @@
// LibraryCallKit::tightly_coupled_allocation() is called.
bool _alloc_tightly_coupled;
+ bool _arguments_validated;
+
static const TypeFunc* arraycopy_type() {
const Type** fields = TypeTuple::fields(ParmLimit - TypeFunc::Parms);
fields[Src] = TypeInstPtr::BOTTOM;
@@ -1118,6 +1120,13 @@
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:
enum {
@@ -1143,23 +1152,23 @@
void connect_outputs(GraphKit* kit);
- bool is_arraycopy() const { return _kind == ArrayCopy; }
- bool is_arraycopy_notest() const { return _kind == ArrayCopyNoTest; }
- bool is_clonebasic() const { return _kind == CloneBasic; }
- bool is_cloneoop() const { return _kind == CloneOop; }
- bool is_copyof() const { return _kind == CopyOf; }
- bool is_copyofrange() const { return _kind == CopyOfRange; }
+ bool is_arraycopy() const { assert(_kind != None, "should bet set"); return _kind == ArrayCopy; }
+ bool is_arraycopy_validated() const { assert(_kind != None, "should bet set"); return _kind == ArrayCopy && _arguments_validated; }
+ bool is_clonebasic() const { assert(_kind != None, "should bet set"); return _kind == CloneBasic; }
+ bool is_cloneoop() const { assert(_kind != None, "should bet set"); return _kind == CloneOop; }
+ bool is_copyof() const { assert(_kind != None, "should bet set"); return _kind == CopyOf; }
+ bool is_copyofrange() const { assert(_kind != None, "should bet set"); return _kind == CopyOfRange; }
- void set_arraycopy() { _kind = ArrayCopy; }
- void set_arraycopy_notest() { _kind = ArrayCopyNoTest; }
- void set_clonebasic() { _kind = CloneBasic; }
- void set_cloneoop() { _kind = CloneOop; }
- void set_copyof() { _kind = CopyOf; }
- void set_copyofrange() { _kind = CopyOfRange; }
+ void set_arraycopy(bool validated) { assert(_kind == None, "shouldn't bet set yet"); _kind = ArrayCopy; _arguments_validated = validated; }
+ void set_clonebasic() { assert(_kind == None, "shouldn't bet set yet"); _kind = CloneBasic; }
+ void set_cloneoop() { assert(_kind == None, "shouldn't bet set yet"); _kind = CloneOop; }
+ void set_copyof() { assert(_kind == None, "shouldn't bet set yet"); _kind = CopyOf; _arguments_validated = false; }
+ void set_copyofrange() { assert(_kind == None, "shouldn't bet set yet"); _kind = CopyOfRange; _arguments_validated = false; }
virtual int Opcode() const;
virtual uint size_of() const; // Size is bigger
virtual bool guaranteed_safepoint() { return false; }
+ virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
bool is_alloc_tightly_coupled() const { return _alloc_tightly_coupled; }
--- a/hotspot/src/share/vm/opto/compile.cpp Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/src/share/vm/opto/compile.cpp Thu Jan 08 17:45:10 2015 -0500
@@ -774,7 +774,9 @@
}
JVMState* jvms = build_start_state(start(), tf());
if ((jvms = cg->generate(jvms)) == NULL) {
- record_method_not_compilable("method parse failed");
+ if (!failure_reason_is(C2Compiler::retry_class_loading_during_parsing())) {
+ record_method_not_compilable("method parse failed");
+ }
return;
}
GraphKit kit(jvms);
--- a/hotspot/src/share/vm/opto/library_call.cpp Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/src/share/vm/opto/library_call.cpp Thu Jan 08 17:45:10 2015 -0500
@@ -4475,8 +4475,11 @@
ArrayCopyNode* ac = ArrayCopyNode::make(this, false, src, NULL, dest, NULL, countx, false);
ac->set_clonebasic();
Node* n = _gvn.transform(ac);
- assert(n == ac, "cannot disappear");
- set_predefined_output_for_runtime_call(ac, ac->in(TypeFunc::Memory), raw_adr_type);
+ if (n == ac) {
+ 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 (card_mark) {
@@ -4541,6 +4544,26 @@
Node* obj = null_check_receiver();
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);
const TypeKlassPtr* tklass = _gvn.type(obj_klass)->isa_klassptr();
const TypeOopPtr* toop = ((tklass != NULL)
@@ -4743,7 +4766,7 @@
sfpt->set_memory(map()->memory());
}
- bool notest = false;
+ bool validated = false;
const Type* src_type = _gvn.type(src);
const Type* dest_type = _gvn.type(dest);
@@ -4847,7 +4870,7 @@
if (!too_many_traps(Deoptimization::Reason_intrinsic) && !src->is_top() && !dest->is_top()) {
// validate arguments: enables transformation the ArrayCopyNode
- notest = true;
+ validated = true;
RegionNode* slow_region = new RegionNode(1);
record_for_igvn(slow_region);
@@ -4922,13 +4945,15 @@
load_object_klass(src), load_object_klass(dest),
load_array_length(src), load_array_length(dest));
- if (notest) {
- ac->set_arraycopy_notest();
- }
+ ac->set_arraycopy(validated);
Node* n = _gvn.transform(ac);
- assert(n == ac, "cannot disappear");
- ac->connect_outputs(this);
+ if (n == ac) {
+ ac->connect_outputs(this);
+ } else {
+ assert(validated, "shouldn't transform if all arguments not validated");
+ set_all_memory(n);
+ }
return true;
}
--- a/hotspot/src/share/vm/opto/macroArrayCopy.cpp Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/src/share/vm/opto/macroArrayCopy.cpp Thu Jan 08 17:45:10 2015 -0500
@@ -519,7 +519,8 @@
// Test S[] against D[], not S against D, because (probably)
// the secondary supertype cache is less busy for S[] than S.
// 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
if (not_subtype_ctrl != top()) {
Node* local_ctrl = not_subtype_ctrl;
@@ -1109,7 +1110,7 @@
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,
// we do not make a fast path for this call. Instead, we let the call remain as it
@@ -1191,7 +1192,7 @@
RegionNode* slow_region = new RegionNode(1);
transform_later(slow_region);
- if (!ac->is_arraycopy_notest()) {
+ if (!ac->is_arraycopy_validated()) {
// (3) operands must not be null
// We currently perform our null checks with the null_check routine.
// This means that the null exceptions will be reported in the caller
--- a/hotspot/src/share/vm/opto/parse1.cpp Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/src/share/vm/opto/parse1.cpp Thu Jan 08 17:45:10 2015 -0500
@@ -27,6 +27,7 @@
#include "interpreter/linkResolver.hpp"
#include "oops/method.hpp"
#include "opto/addnode.hpp"
+#include "opto/c2compiler.hpp"
#include "opto/castnode.hpp"
#include "opto/idealGraphPrinter.hpp"
#include "opto/locknode.hpp"
@@ -986,7 +987,18 @@
if (tf()->range()->cnt() > TypeFunc::Parms) {
const Type* ret_type = tf()->range()->field_at(TypeFunc::Parms);
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);
}
--- a/hotspot/src/share/vm/prims/whitebox.cpp Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/src/share/vm/prims/whitebox.cpp Thu Jan 08 17:45:10 2015 -0500
@@ -1123,6 +1123,16 @@
attemptedNoSafepointValue == JNI_TRUE);
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
int WhiteBox::offset_for_field(const char* field_name, oop object,
Symbol* signature_symbol) {
@@ -1321,6 +1331,8 @@
{CC"getThreadStackSize", CC"()J", (void*)&WB_GetThreadStackSize },
{CC"getThreadRemainingStackSize", CC"()J", (void*)&WB_GetThreadRemainingStackSize },
{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
--- a/hotspot/test/TEST.groups Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/TEST.groups Thu Jan 08 17:45:10 2015 -0500
@@ -145,6 +145,7 @@
gc/survivorAlignment \
runtime/InternalApi/ThreadCpuTimesDeadlock.java \
serviceability/threads/TestFalseDeadLock.java \
+ compiler/codecache/jmx
# Compact 2 adds full VM tests
compact2 = \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arraycopy/TestArrayCopyMacro.java Thu Jan 08 17:45:10 2015 -0500
@@ -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]);
+ }
+ }
+ }
+ }
+}
--- a/hotspot/test/compiler/arraycopy/TestArrayOfNoTypeCheck.java Thu Jan 08 15:44:46 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * 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
- * @bug 8055910
- * @summary Arrays.copyOf doesn't perform subtype check
- * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestArrayOfNoTypeCheck
- *
- */
-
-import java.util.Arrays;
-
-public class TestArrayOfNoTypeCheck {
-
- static class A {
- }
-
- static class B extends A {
- }
-
- static B[] test(A[] arr) {
- return Arrays.copyOf(arr, 10, B[].class);
- }
-
- static public void main(String[] args) {
- A[] arr = new A[20];
- for (int i = 0; i < 20000; i++) {
- test(arr);
- }
- A[] arr2 = new A[20];
- arr2[0] = new A();
- boolean exception = false;
- try {
- test(arr2);
- } catch (ArrayStoreException ase) {
- exception = true;
- }
- if (!exception) {
- throw new RuntimeException("TEST FAILED: ArrayStoreException not thrown");
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arraycopy/TestArraysCopyOfNoTypeCheck.java Thu Jan 08 17:45:10 2015 -0500
@@ -0,0 +1,63 @@
+/*
+ * 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
+ * @bug 8055910
+ * @summary Arrays.copyOf doesn't perform subtype check
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestArraysCopyOfNoTypeCheck
+ *
+ */
+
+import java.util.Arrays;
+
+public class TestArraysCopyOfNoTypeCheck {
+
+ static class A {
+ }
+
+ static class B extends A {
+ }
+
+ static B[] test(A[] arr) {
+ return Arrays.copyOf(arr, 10, B[].class);
+ }
+
+ static public void main(String[] args) {
+ A[] arr = new A[20];
+ for (int i = 0; i < 20000; i++) {
+ test(arr);
+ }
+ A[] arr2 = new A[20];
+ arr2[0] = new A();
+ boolean exception = false;
+ try {
+ test(arr2);
+ } catch (ArrayStoreException ase) {
+ exception = true;
+ }
+ if (!exception) {
+ throw new RuntimeException("TEST FAILED: ArrayStoreException not thrown");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arraycopy/TestInstanceCloneAsLoadsStores.java Thu Jan 08 17:45:10 2015 -0500
@@ -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");
+ }
+
+ }
+}
--- a/hotspot/test/compiler/ciReplay/TestSA.sh Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/compiler/ciReplay/TestSA.sh Thu Jan 08 17:45:10 2015 -0500
@@ -26,7 +26,7 @@
##
## @test
## @bug 8011675
-## @ignore 8031978
+## @ignore 8029528
## @summary testing of ciReplay with using generated by SA replay.txt
## @author igor.ignatyev@oracle.com
## @run shell TestSA.sh
@@ -69,7 +69,6 @@
echo "dumpreplaydata -a > ${replay_data}" | \
${JAVA} ${TESTOPTS} \
- -cp ${TESTJAVA}${FS}lib${FS}sa-jdi.jar \
sun.jvm.hotspot.CLHSDB ${JAVA} ${core_file}
if [ ! -s ${replay_data} ]
--- a/hotspot/test/compiler/ciReplay/common.sh Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/compiler/ciReplay/common.sh Thu Jan 08 17:45:10 2015 -0500
@@ -263,10 +263,10 @@
dir=`dirname $core_with_dir`
file=`basename $core_with_dir`
# add <core_path>/core.<pid> core
- core_locations="'$core_with_dir' '$file'"
+ core_locations='$core_with_dir' '$file'
if [ -n "${core_with_pid}" ]
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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/cli/TestSegmentedCodeCacheOption.java Thu Jan 08 17:45:10 2015 -0500
@@ -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());
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/cli/codeheapsize/CodeCacheFreeSpaceRunner.java Thu Jan 08 17:45:10 2015 -0500
@@ -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)));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/cli/codeheapsize/GenericCodeHeapSizeRunner.java Thu Jan 08 17:45:10 2015 -0500
@@ -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));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/cli/codeheapsize/JVMStartupRunner.java Thu Jan 08 17:45:10 2015 -0500
@@ -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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/cli/codeheapsize/TestCodeHeapSizeOptions.java Thu Jan 08 17:45:10 2015 -0500
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/cli/common/CodeCacheCLITestBase.java Thu Jan 08 17:45:10 2015 -0500
@@ -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);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/cli/common/CodeCacheCLITestCase.java Thu Jan 08 17:45:10 2015 -0500
@@ -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;
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/cli/common/CodeCacheInfoFormatter.java Thu Jan 08 17:45:10 2015 -0500
@@ -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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/cli/common/CodeCacheOptions.java Thu Jan 08 17:45:10 2015 -0500
@@ -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.");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/cli/printcodecache/PrintCodeCacheRunner.java Thu Jan 08 17:45:10 2015 -0500
@@ -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)));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/cli/printcodecache/TestPrintCodeCacheOption.java Thu Jan 08 17:45:10 2015 -0500
@@ -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();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/dtrace/SegmentedCodeCacheDtraceTest.java Thu Jan 08 17:45:10 2015 -0500
@@ -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;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/dtrace/SegmentedCodeCacheDtraceTestScript.d Thu Jan 08 17:45:10 2015 -0500
@@ -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();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/dtrace/SegmentedCodeCacheDtraceTestWorker.java Thu Jan 08 17:45:10 2015 -0500
@@ -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");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/jmx/BeanTypeTest.java Thu Jan 08 17:45:10 2015 -0500
@@ -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());
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/jmx/CodeCacheUtils.java Thu Jan 08 17:45:10 2015 -0500
@@ -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));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/jmx/CodeHeapBeanPresenceTest.java Thu Jan 08 17:45:10 2015 -0500
@@ -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());
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/jmx/GetUsageTest.java Thu Jan 08 17:45:10 2015 -0500
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/jmx/InitialAndMaxUsageTest.java Thu Jan 08 17:45:10 2015 -0500
@@ -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());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/jmx/ManagerNamesTest.java Thu Jan 08 17:45:10 2015 -0500
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/jmx/MemoryPoolsPresenceTest.java Thu Jan 08 17:45:10 2015 -0500
@@ -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");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java Thu Jan 08 17:45:10 2015 -0500
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java Thu Jan 08 17:45:10 2015 -0500
@@ -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();
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java Thu Jan 08 17:45:10 2015 -0500
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededSeveralTimesTest.java Thu Jan 08 17:45:10 2015 -0500
@@ -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
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java Thu Jan 08 17:45:10 2015 -0500
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java Thu Jan 08 17:45:10 2015 -0500
@@ -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());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdNotExceededTest.java Thu Jan 08 17:45:10 2015 -0500
@@ -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());
+ }
+}
--- a/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java Thu Jan 08 17:45:10 2015 -0500
@@ -127,10 +127,7 @@
@Override
public String[] getMethodsToCompileNames() {
- return new String[] {
- getMethodWithLockName(),
- Unsafe.class.getName() + "::addressSize"
- };
+ return new String[] { getMethodWithLockName() };
}
public void lock(boolean abort) {
@@ -148,10 +145,12 @@
public static void main(String args[]) throws Throwable {
Asserts.assertGTE(args.length, 1, "One argument required.");
Test t = new Test();
- if (Boolean.valueOf(args[0])) {
+ boolean shouldBeInflated = Boolean.valueOf(args[0]);
+ if (shouldBeInflated) {
AbortProvoker.inflateMonitor(t.monitor);
}
for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) {
+ AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
t.lock(i >= Test.WARMUP_ITERATIONS);
}
}
--- a/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java Thu Jan 08 17:45:10 2015 -0500
@@ -157,10 +157,7 @@
@Override
public String[] getMethodsToCompileNames() {
- return new String[] {
- getMethodWithLockName(),
- sun.misc.Unsafe.class.getName() + "::forceAbort"
- };
+ return new String[] { getMethodWithLockName() };
}
public void forceAbort(int a[], boolean abort) {
@@ -183,13 +180,15 @@
public static void main(String args[]) throws Throwable {
Test t = new Test();
- if (Boolean.valueOf(args[0])) {
+ boolean shouldBeInflated = Boolean.valueOf(args[0]);
+ if (shouldBeInflated) {
AbortProvoker.inflateMonitor(t.monitor);
}
int tmp[] = new int[1];
for (int i = 0; i < Test.ITERATIONS; i++ ) {
+ AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
if (i == Test.RANGE_CHECK_AT) {
t.forceAbort(new int[0], false);
} else {
--- a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java Thu Jan 08 17:45:10 2015 -0500
@@ -130,10 +130,7 @@
@Override
public String[] getMethodsToCompileNames() {
- return new String[] {
- getMethodWithLockName(),
- sun.misc.Unsafe.class.getName() + "::addressSize"
- };
+ return new String[] { getMethodWithLockName() };
}
public void forceAbort(boolean abort) {
@@ -151,11 +148,12 @@
public static void main(String args[]) throws Throwable {
Asserts.assertGTE(args.length, 1, "One argument required.");
Test t = new Test();
-
- if (Boolean.valueOf(args[0])) {
+ boolean shouldBeInflated = Boolean.valueOf(args[0]);
+ if (shouldBeInflated) {
AbortProvoker.inflateMonitor(t.monitor);
}
for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
+ AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
t.forceAbort(
i == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD);
}
--- a/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java Thu Jan 08 17:45:10 2015 -0500
@@ -143,10 +143,7 @@
@Override
public String[] getMethodsToCompileNames() {
- return new String[] {
- getMethodWithLockName(),
- sun.misc.Unsafe.class.getName() + "::addressSize"
- };
+ return new String[] { getMethodWithLockName() };
}
public void lock(boolean abort) {
@@ -164,11 +161,12 @@
public static void main(String args[]) throws Throwable {
Asserts.assertGTE(args.length, 1, "One argument required.");
Test t = new Test();
-
- if (Boolean.valueOf(args[0])) {
+ boolean shouldBeInflated = Boolean.valueOf(args[0]);
+ if (shouldBeInflated) {
AbortProvoker.inflateMonitor(t.monitor);
}
for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) {
+ AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
t.lock(i % 2 == 1);
}
}
--- a/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Thu Jan 08 17:45:10 2015 -0500
@@ -117,9 +117,7 @@
@Override
public String[] getMethodsToCompileNames() {
- return new String[] {
- getMethodWithLockName()
- };
+ return new String[] { getMethodWithLockName() };
}
public void lock() {
@@ -135,11 +133,13 @@
public static void main(String args[]) throws Throwable {
Asserts.assertGTE(args.length, 1, "One argument required.");
Test test = new Test();
-
- if (Boolean.valueOf(args[0])) {
+ boolean shouldBeInflated = Boolean.valueOf(args[0]);
+ if (shouldBeInflated) {
AbortProvoker.inflateMonitor(test.monitor);
}
for (long i = 0L; i < Test.TOTAL_ITERATIONS; i++) {
+ AbortProvoker.verifyMonitorState(test.monitor,
+ shouldBeInflated);
test.lock();
}
}
--- a/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java Thu Jan 08 17:45:10 2015 -0500
@@ -52,7 +52,7 @@
* Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times before
* lock inflation and the same amount of times after inflation.
* 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
* happened: it could be {@code AbortType.RETRIABLE} or
* {@code AbortType.MEM_CONFLICT}, but unfortunately abort can has both these
@@ -101,7 +101,6 @@
}
public static class Test {
-
/**
* Usage:
* Test <provoker type>
@@ -113,10 +112,12 @@
AbortProvoker provoker
= AbortType.lookup(Integer.valueOf(args[0])).provoker();
for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
+ AbortProvoker.verifyMonitorState(provoker, false /*deflated*/);
provoker.forceAbort();
}
provoker.inflateMonitor();
for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
+ AbortProvoker.verifyMonitorState(provoker, true /*inflated*/);
provoker.forceAbort();
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/CompilerUtils.java Thu Jan 08 17:45:10 2015 -0500
@@ -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];
+ }
+}
--- a/hotspot/test/compiler/testlibrary/rtm/AbortProvoker.java Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/compiler/testlibrary/rtm/AbortProvoker.java Thu Jan 08 17:45:10 2015 -0500
@@ -29,8 +29,7 @@
import java.util.concurrent.CyclicBarrier;
import com.oracle.java.testlibrary.Asserts;
-import com.oracle.java.testlibrary.Utils;
-import sun.misc.Unsafe;
+import sun.hotspot.WhiteBox;
/**
* Base class for different transactional execution abortion
@@ -38,6 +37,9 @@
*/
public abstract class AbortProvoker implements CompilableTest {
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}.
* Inflation is forced by entering the same monitor from
@@ -48,36 +50,76 @@
* @throws Exception if something went wrong.
*/
public static Object inflateMonitor(Object monitor) throws Exception {
- Unsafe unsafe = Utils.getUnsafe();
CyclicBarrier barrier = new CyclicBarrier(2);
Runnable inflatingRunnable = () -> {
- unsafe.monitorEnter(monitor);
- try {
- barrier.await();
- barrier.await();
- } catch (InterruptedException | BrokenBarrierException e) {
- throw new RuntimeException(
- "Synchronization issue occurred.", e);
- } finally {
- unsafe.monitorExit(monitor);
+ synchronized (monitor) {
+ try {
+ barrier.await();
+ } catch (BrokenBarrierException | InterruptedException e) {
+ throw new RuntimeException(
+ "Synchronization issue occurred.", e);
+ }
+ 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);
+ t.setDaemon(true);
t.start();
// Wait until thread t enters the monitor.
barrier.await();
- // At this point monitor will be owned by thread t,
- // so our attempt to enter the same monitor will force
- // monitor inflation.
- Asserts.assertFalse(unsafe.tryMonitorEnter(monitor),
- "Not supposed to enter the monitor first");
- barrier.await();
- t.join();
+ synchronized (monitor) {
+ // At this point thread t is already waiting on the monitor.
+ // Modifying static field just to avoid lock's elimination.
+ sharedState++;
+ }
+ verifyMonitorState(monitor, true /* inflated */);
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
@@ -120,6 +162,7 @@
}
for (long i = 0; i < iterations; i++) {
+ AbortProvoker.verifyMonitorState(provoker, monitorShouldBeInflated);
provoker.forceAbort();
}
}
--- a/hotspot/test/compiler/testlibrary/rtm/BusyLock.java Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/compiler/testlibrary/rtm/BusyLock.java Thu Jan 08 17:45:10 2015 -0500
@@ -77,7 +77,7 @@
}
}
- public void test() {
+ public void syncAndTest() {
try {
barrier.await();
// wait until monitor is locked by a ::run method
@@ -85,6 +85,10 @@
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException("Synchronization error happened.", e);
}
+ test();
+ }
+
+ public void test() {
synchronized(monitor) {
BusyLock.field++;
}
@@ -130,7 +134,7 @@
Thread t = new Thread(busyLock);
t.start();
- busyLock.test();
+ busyLock.syncAndTest();
t.join();
}
}
--- a/hotspot/test/compiler/testlibrary/rtm/MemoryConflictProvoker.java Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/compiler/testlibrary/rtm/MemoryConflictProvoker.java Thu Jan 08 17:45:10 2015 -0500
@@ -69,11 +69,6 @@
* Accesses and modifies memory region from within the transaction.
*/
public void transactionalRegion() {
- try {
- barrier.await();
- } catch (InterruptedException | BrokenBarrierException e) {
- throw new RuntimeException(e);
- }
for (int i = 0; i < MemoryConflictProvoker.INNER_ITERATIONS; i++) {
synchronized(monitor) {
MemoryConflictProvoker.field--;
@@ -86,6 +81,11 @@
try {
Thread t = new Thread(conflictingThread);
t.start();
+ try {
+ barrier.await();
+ } catch (InterruptedException | BrokenBarrierException e) {
+ throw new RuntimeException(e);
+ }
transactionalRegion();
t.join();
} catch (Exception e) {
--- a/hotspot/test/compiler/testlibrary/rtm/RTMTestBase.java Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/compiler/testlibrary/rtm/RTMTestBase.java Thu Jan 08 17:45:10 2015 -0500
@@ -240,7 +240,8 @@
Collections.addAll(finalVMOpts, "-Xcomp", "-server",
"-XX:-TieredCompilation", "-XX:+UseRTMLocking",
CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS,
- CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS);
+ CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
+ "-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI");
if (test != null) {
for (String method : test.getMethodsToCompileNames()) {
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/ByteCodeLoader.java Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/ByteCodeLoader.java Thu Jan 08 17:45:10 2015 -0500
@@ -37,6 +37,7 @@
public class ByteCodeLoader extends SecureClassLoader {
private final String className;
private final byte[] byteCode;
+ private volatile Class<?> holder;
/**
* Creates a new {@code ByteCodeLoader} ready to load a class with the
@@ -51,6 +52,21 @@
}
@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
protected Class<?> findClass(String name) throws ClassNotFoundException {
if (!name.equals(className)) {
throw new ClassNotFoundException(name);
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/InfiniteLoop.java Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/InfiniteLoop.java Thu Jan 08 17:45:10 2015 -0500
@@ -54,7 +54,9 @@
try {
while (true) {
target.run();
- Thread.sleep(mills);
+ if (mills > 0) {
+ Thread.sleep(mills);
+ }
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Platform.java Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Platform.java Thu Jan 08 17:45:10 2015 -0500
@@ -34,6 +34,7 @@
private static final String osArch = System.getProperty("os.arch");
private static final String vmName = System.getProperty("java.vm.name");
private static final String userName = System.getProperty("user.name");
+ private static final String compiler = System.getProperty("sun.management.compiler");
public static boolean isClient() {
return vmName.endsWith(" Client VM");
@@ -55,6 +56,10 @@
return vmName.contains("Embedded");
}
+ public static boolean isTieredSupported() {
+ return compiler.contains("Tiered Compilers");
+ }
+
public static boolean is32bit() {
return dataModel.equals("32");
}
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java Thu Jan 08 17:45:10 2015 -0500
@@ -40,6 +40,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Random;
+import java.util.function.BooleanSupplier;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -306,25 +307,6 @@
}
/**
- * 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,
* or null if not found.
* @param filename name of the file to read
@@ -396,6 +378,52 @@
}
/**
+ * 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
* @param tOut the timeout value to be adjusted
* @return The timeout value adjusted for the value of "test.timeout.factor"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/dtrace/DtraceResultsAnalyzer.java Thu Jan 08 17:45:10 2015 -0500
@@ -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);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/dtrace/DtraceRunner.java Thu Jan 08 17:45:10 2015 -0500
@@ -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;
+ }
+}
--- a/hotspot/test/testlibrary/ctw/test/Bar.java Thu Jan 08 15:44:46 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-public class Bar {
- private static void staticMethod() { }
- public void method() { }
- protected Bar() { }
-}
--- a/hotspot/test/testlibrary/ctw/test/ClassesDirTest.java Thu Jan 08 15:44:46 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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);
- }
-}
--- a/hotspot/test/testlibrary/ctw/test/ClassesListTest.java Thu Jan 08 15:44:46 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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);
- }
-}
--- a/hotspot/test/testlibrary/ctw/test/CtwTest.java Thu Jan 08 15:44:46 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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()]));
- }
-}
--- a/hotspot/test/testlibrary/ctw/test/Foo.java Thu Jan 08 15:44:46 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-public class Foo {
- private static void staticMethod() { }
- public void method() { }
- protected Foo() { }
-}
--- a/hotspot/test/testlibrary/ctw/test/JarDirTest.java Thu Jan 08 15:44:46 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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);
- }
-
-}
--- a/hotspot/test/testlibrary/ctw/test/JarsTest.java Thu Jan 08 15:44:46 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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);
- }
-
-}
--- a/hotspot/test/testlibrary/ctw/test/classes.lst Thu Jan 08 15:44:46 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-java.lang.String
-java.lang.Object
-Foo
-Bar
--- a/hotspot/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java Thu Jan 08 15:44:46 2015 +0100
+++ b/hotspot/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java Thu Jan 08 17:45:10 2015 -0500
@@ -48,7 +48,7 @@
OS("isLinux", "isSolaris", "isWindows", "isOSX"),
VM_TYPE("isClient", "isServer", "isGraal", "isMinimal"),
IGNORED("isEmbedded", "isDebugBuild", "shouldSAAttach",
- "canPtraceAttachLinux", "canAttachOSX");
+ "canPtraceAttachLinux", "canAttachOSX", "isTieredSupported");
public final List<String> methodNames;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary_tests/TestPlatformIsTieredSupported.java Thu Jan 08 17:45:10 2015 -0500
@@ -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.");
+ }
+}