This commit is contained in:
Yumin Qi 2015-01-10 12:35:44 -08:00
commit d4fd7377f4
1038 changed files with 31044 additions and 6081 deletions

View File

@ -285,3 +285,5 @@ b409bc51bc23cfd51f2bd04ea919ec83535af9d0 jdk9-b37
82f4cb44b2d7af2352f48568a64b7b6a5ae960cd jdk9-b40
9fffb959eb4197ff806e4ac12244761815b4deee jdk9-b41
3107be2ba9c6e208a0b86bc7100a141abbc5b5fb jdk9-b42
6494b13f88a867026ee316b444d9a4fa589dd6bd jdk9-b43
abbfccd659b91a7bb815d5e36fed635dcdd40f31 jdk9-b44

View File

@ -285,3 +285,5 @@ d42c0a90afc3c66ca87543076ec9aafd4b4680de jdk9-b38
cf136458ee747e151a27aa9ea0c1492ea55ef3e7 jdk9-b40
67395f7ca2db3b52e3a62a84888487de5cb9210a jdk9-b41
f7c11da0b0481d49cc7a65a453336c108191e821 jdk9-b42
02ee8c65622e8bd97496d584e22fc7dcf0edc4ae jdk9-b43
8994f5d87b3bb5e8d317d4e8ccb326da1a73684a jdk9-b44

View File

@ -4329,7 +4329,7 @@ TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++"
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
DATE_WHEN_GENERATED=1418036274
DATE_WHEN_GENERATED=1418395009
###############################################################################
#
@ -13965,7 +13965,8 @@ $as_echo "$COMPILE_TYPE" >&6; }
# ZERO_ARCHDEF is used to enable architecture-specific code
case "${OPENJDK_TARGET_CPU}" in
ppc*) ZERO_ARCHDEF=PPC ;;
ppc) ZERO_ARCHDEF=PPC32 ;;
ppc64) ZERO_ARCHDEF=PPC64 ;;
s390*) ZERO_ARCHDEF=S390 ;;
sparc*) ZERO_ARCHDEF=SPARC ;;
x86_64*) ZERO_ARCHDEF=AMD64 ;;

View File

@ -367,7 +367,8 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS],
# ZERO_ARCHDEF is used to enable architecture-specific code
case "${OPENJDK_TARGET_CPU}" in
ppc*) ZERO_ARCHDEF=PPC ;;
ppc) ZERO_ARCHDEF=PPC32 ;;
ppc64) ZERO_ARCHDEF=PPC64 ;;
s390*) ZERO_ARCHDEF=S390 ;;
sparc*) ZERO_ARCHDEF=SPARC ;;
x86_64*) ZERO_ARCHDEF=AMD64 ;;

View File

@ -106,12 +106,15 @@ if [ ${vflag} = "true" ] ; then
echo "# Mercurial command: ${command}" > ${status_output}
fi
# capture command options and arguments (if any)
command_args="${@:-}"
# At this point all command options and args are in "$@".
# Always use "$@" (within double quotes) to avoid breaking
# args with spaces into separate args.
if [ ${vflag} = "true" ] ; then
echo "# Mercurial command arguments: ${command_args}" > ${status_output}
echo "# Mercurial command argument count: $#" > ${status_output}
for cmdarg in "$@" ; do
echo "# Mercurial command argument: ${cmdarg}" > ${status_output}
done
fi
# Clean out the temporary directory that stores the pid files.
@ -205,13 +208,14 @@ if [ "${command}" = "clone" -o "${command}" = "fclone" -o "${command}" = "tclone
pull_default_tail=`echo ${pull_default} | sed -e 's@^.*://[^/]*/\(.*\)@\1@'`
if [ -n "${command_args}" ] ; then
if [ $# -gt 0 ] ; then
# if there is an "extra sources" path then reparent "extra" repos to that path
if [ "x${pull_default}" = "x${pull_default_tail}" ] ; then
echo "ERROR: Need initial clone from non-local source" > ${status_output}
exit 1
fi
pull_extra="${command_args}/${pull_default_tail}"
# assume that "extra sources" path is the first arg
pull_extra="${1}/${pull_default_tail}"
# determine which extra subrepos need to be cloned.
for i in ${subrepos_extra} ; do
@ -356,8 +360,8 @@ else
(PYTHONUNBUFFERED=true hg${global_opts} clone ${clone_newrepo} ${i}; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 &
else
# run the command.
echo "cd ${i} && hg${global_opts} ${command} ${command_args}" > ${status_output}
cd ${i} && (PYTHONUNBUFFERED=true hg${global_opts} ${command} ${command_args}; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 &
echo "cd ${i} && hg${global_opts} ${command} ${@}" > ${status_output}
cd ${i} && (PYTHONUNBUFFERED=true hg${global_opts} ${command} "${@}"; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 &
fi
echo $! > ${tmp}/${repopidfile}.pid

View File

@ -285,3 +285,5 @@ ffd90c81d4ef9d94d880fc852e2fc482ecd9b374 jdk9-b36
e27c725d6c9d155667b35255f442d4ceb8c3c084 jdk9-b40
1908b886ba1eda46fa725cf1160fe5d30fd1a7e5 jdk9-b41
078bb11af876fe528d4b516f33ad4dd9bb60549e jdk9-b42
9645e35616b60c5c07b4fdf11a132afc8081dfa8 jdk9-b43
1f57bd728c9e6865ccb9d43ccd80a1c11230a32f jdk9-b44

View File

@ -445,3 +445,5 @@ c363a8b87e477ee45d6d3cb2a36cb365141bc596 jdk9-b38
6b09b3193d731e3288e2a240c504a20d0a06c766 jdk9-b40
1d29b13e8a515a7ea3b882f140576d5d675bc11f jdk9-b41
38cb4fbd47e3472bd1b5ebac83bda96fe4869c4f jdk9-b42
65a9747147b8090037541040ba67156ec914db6a jdk9-b43
43a44b56dca61a4d766a20f0528fdd8b5ceff873 jdk9-b44

View File

@ -59,7 +59,7 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
_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 @@ ciInstanceKlass::ciInstanceKlass(ciSymbol* name,
_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 @@ ciInstanceKlass::compute_nonstatic_fields_impl(GrowableArray<ciField*>*
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
//

View File

@ -64,6 +64,7 @@ private:
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 @@ private:
// 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 @@ public:
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, "");

View File

@ -99,8 +99,8 @@ void G1DefaultAllocator::release_gc_alloc_regions(uint no_of_gc_workers, Evacuat
}
if (ResizePLAB) {
_g1h->_survivor_plab_stats.adjust_desired_plab_sz(no_of_gc_workers);
_g1h->_old_plab_stats.adjust_desired_plab_sz(no_of_gc_workers);
_g1h->alloc_buffer_stats(InCSetState::Young)->adjust_desired_plab_sz(no_of_gc_workers);
_g1h->alloc_buffer_stats(InCSetState::Old)->adjust_desired_plab_sz(no_of_gc_workers);
}
}

View File

@ -2068,7 +2068,7 @@ void G1CollectedHeap::stop() {
}
void G1CollectedHeap::clear_humongous_is_live_table() {
guarantee(G1ReclaimDeadHumongousObjectsAtYoungGC, "Should only be called if true");
guarantee(G1EagerReclaimHumongousObjects, "Should only be called if true");
_humongous_is_live.clear();
}
@ -3485,8 +3485,24 @@ class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure {
private:
size_t _total_humongous;
size_t _candidate_humongous;
DirtyCardQueue _dcq;
bool humongous_region_is_candidate(uint index) {
HeapRegion* region = G1CollectedHeap::heap()->region_at(index);
assert(region->is_starts_humongous(), "Must start a humongous object");
HeapRegionRemSet* const rset = region->rem_set();
bool const allow_stale_refs = G1EagerReclaimHumongousObjectsWithStaleRefs;
return !oop(region->bottom())->is_objArray() &&
((allow_stale_refs && rset->occupancy_less_or_equal_than(G1RSetSparseRegionEntries)) ||
(!allow_stale_refs && rset->is_empty()));
}
public:
RegisterHumongousWithInCSetFastTestClosure() : _total_humongous(0), _candidate_humongous(0) {
RegisterHumongousWithInCSetFastTestClosure()
: _total_humongous(0),
_candidate_humongous(0),
_dcq(&JavaThread::dirty_card_queue_set()) {
}
virtual bool doHeapRegion(HeapRegion* r) {
@ -3496,11 +3512,29 @@ class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
uint region_idx = r->hrm_index();
bool is_candidate = !g1h->humongous_region_is_always_live(region_idx);
// Is_candidate already filters out humongous regions with some remembered set.
// This will not lead to humongous object that we mistakenly keep alive because
// during young collection the remembered sets will only be added to.
bool is_candidate = humongous_region_is_candidate(region_idx);
// Is_candidate already filters out humongous object with large remembered sets.
// If we have a humongous object with a few remembered sets, we simply flush these
// remembered set entries into the DCQS. That will result in automatic
// re-evaluation of their remembered set entries during the following evacuation
// phase.
if (is_candidate) {
if (!r->rem_set()->is_empty()) {
guarantee(r->rem_set()->occupancy_less_or_equal_than(G1RSetSparseRegionEntries),
"Found a not-small remembered set here. This is inconsistent with previous assumptions.");
G1SATBCardTableLoggingModRefBS* bs = g1h->g1_barrier_set();
HeapRegionRemSetIterator hrrs(r->rem_set());
size_t card_index;
while (hrrs.has_next(card_index)) {
jbyte* card_ptr = (jbyte*)bs->byte_for_index(card_index);
if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
*card_ptr = CardTableModRefBS::dirty_card_val();
_dcq.enqueue(card_ptr);
}
}
r->rem_set()->clear_locked();
}
assert(r->rem_set()->is_empty(), "At this point any humongous candidate remembered set must be empty.");
g1h->register_humongous_region_with_in_cset_fast_test(region_idx);
_candidate_humongous++;
}
@ -3511,23 +3545,32 @@ class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure {
size_t total_humongous() const { return _total_humongous; }
size_t candidate_humongous() const { return _candidate_humongous; }
void flush_rem_set_entries() { _dcq.flush(); }
};
void G1CollectedHeap::register_humongous_regions_with_in_cset_fast_test() {
if (!G1ReclaimDeadHumongousObjectsAtYoungGC) {
g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0, 0);
if (!G1EagerReclaimHumongousObjects) {
g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0.0, 0, 0);
return;
}
double time = os::elapsed_counter();
RegisterHumongousWithInCSetFastTestClosure cl;
heap_region_iterate(&cl);
g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(cl.total_humongous(),
time = ((double)(os::elapsed_counter() - time) / os::elapsed_frequency()) * 1000.0;
g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(time,
cl.total_humongous(),
cl.candidate_humongous());
_has_humongous_reclaim_candidates = cl.candidate_humongous() > 0;
if (_has_humongous_reclaim_candidates || G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
if (_has_humongous_reclaim_candidates || G1TraceEagerReclaimHumongousObjects) {
clear_humongous_is_live_table();
}
// Finally flush all remembered set entries to re-check into the global DCQS.
cl.flush_rem_set_entries();
}
void
@ -6140,22 +6183,20 @@ class G1FreeHumongousRegionClosure : public HeapRegionClosure {
// are completely up-to-date wrt to references to the humongous object.
//
// Other implementation considerations:
// - never consider object arrays: while they are a valid target, they have not
// been observed to be used as temporary objects.
// - they would also pose considerable effort for cleaning up the the remembered
// sets.
// While this cleanup is not strictly necessary to be done (or done instantly),
// given that their occurrence is very low, this saves us this additional
// complexity.
// - never consider object arrays at this time because they would pose
// considerable effort for cleaning up the the remembered sets. This is
// required because stale remembered sets might reference locations that
// are currently allocated into.
uint region_idx = r->hrm_index();
if (g1h->humongous_is_live(region_idx) ||
g1h->humongous_region_is_always_live(region_idx)) {
if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
gclog_or_tty->print_cr("Live humongous %d region %d size "SIZE_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
r->is_humongous(),
if (G1TraceEagerReclaimHumongousObjects) {
gclog_or_tty->print_cr("Live humongous region %u size "SIZE_FORMAT" start "PTR_FORMAT" length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
region_idx,
obj->size()*HeapWordSize,
r->bottom(),
r->region_num(),
r->rem_set()->occupied(),
r->rem_set()->strong_code_roots_list_length(),
next_bitmap->isMarked(r->bottom()),
@ -6171,12 +6212,11 @@ class G1FreeHumongousRegionClosure : public HeapRegionClosure {
err_msg("Eagerly reclaiming object arrays is not supported, but the object "PTR_FORMAT" is.",
r->bottom()));
if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
gclog_or_tty->print_cr("Reclaim humongous region %d size "SIZE_FORMAT" start "PTR_FORMAT" region %d length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
r->is_humongous(),
if (G1TraceEagerReclaimHumongousObjects) {
gclog_or_tty->print_cr("Dead humongous region %u size "SIZE_FORMAT" start "PTR_FORMAT" length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
region_idx,
obj->size()*HeapWordSize,
r->bottom(),
region_idx,
r->region_num(),
r->rem_set()->occupied(),
r->rem_set()->strong_code_roots_list_length(),
@ -6213,8 +6253,8 @@ class G1FreeHumongousRegionClosure : public HeapRegionClosure {
void G1CollectedHeap::eagerly_reclaim_humongous_regions() {
assert_at_safepoint(true);
if (!G1ReclaimDeadHumongousObjectsAtYoungGC ||
(!_has_humongous_reclaim_candidates && !G1TraceReclaimDeadHumongousObjectsAtYoungGC)) {
if (!G1EagerReclaimHumongousObjects ||
(!_has_humongous_reclaim_candidates && !G1TraceEagerReclaimHumongousObjects)) {
g1_policy()->phase_times()->record_fast_reclaim_humongous_time_ms(0.0, 0);
return;
}

View File

@ -186,32 +186,14 @@ class G1CollectedHeap : public SharedHeap {
friend class SurvivorGCAllocRegion;
friend class OldGCAllocRegion;
friend class G1Allocator;
friend class G1DefaultAllocator;
friend class G1ResManAllocator;
// Closures used in implementation.
template <G1Barrier barrier, G1Mark do_mark_object>
friend class G1ParCopyClosure;
friend class G1IsAliveClosure;
friend class G1EvacuateFollowersClosure;
friend class G1ParScanThreadState;
friend class G1ParScanClosureSuper;
friend class G1ParEvacuateFollowersClosure;
friend class G1ParTask;
friend class G1ParGCAllocator;
friend class G1DefaultParGCAllocator;
friend class G1FreeGarbageRegionClosure;
friend class RefineCardTableEntryClosure;
friend class G1PrepareCompactClosure;
friend class RegionSorter;
friend class RegionResetter;
friend class CountRCClosure;
friend class EvacPopObjClosure;
friend class G1ParCleanupCTTask;
friend class G1FreeHumongousRegionClosure;
// Other related classes.
friend class G1MarkSweep;
friend class HeapRegionClaimer;
// Testing classes.
@ -659,6 +641,9 @@ public:
// Returns whether the given region (which must be a humongous (start) region)
// is to be considered conservatively live regardless of any other conditions.
bool humongous_region_is_always_live(uint index);
// Returns whether the given region (which must be a humongous (start) region)
// is considered a candidate for eager reclamation.
bool humongous_region_is_candidate(uint index);
// Register the given region to be part of the collection set.
inline void register_humongous_region_with_in_cset_fast_test(uint index);
// Register regions with humongous objects (actually on the start region) in

View File

@ -344,11 +344,14 @@ void G1GCPhaseTimes::print(double pause_time_sec) {
_last_redirty_logged_cards_time_ms.print(3, "Parallel Redirty");
_last_redirty_logged_cards_processed_cards.print(3, "Redirtied Cards");
}
if (G1ReclaimDeadHumongousObjectsAtYoungGC) {
print_stats(2, "Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms);
if (G1EagerReclaimHumongousObjects) {
print_stats(2, "Humongous Register", _cur_fast_reclaim_humongous_register_time_ms);
if (G1Log::finest()) {
print_stats(3, "Humongous Total", _cur_fast_reclaim_humongous_total);
print_stats(3, "Humongous Candidate", _cur_fast_reclaim_humongous_candidates);
}
print_stats(2, "Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms);
if (G1Log::finest()) {
print_stats(3, "Humongous Reclaimed", _cur_fast_reclaim_humongous_reclaimed);
}
}

View File

@ -157,6 +157,7 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
double _recorded_non_young_free_cset_time_ms;
double _cur_fast_reclaim_humongous_time_ms;
double _cur_fast_reclaim_humongous_register_time_ms;
size_t _cur_fast_reclaim_humongous_total;
size_t _cur_fast_reclaim_humongous_candidates;
size_t _cur_fast_reclaim_humongous_reclaimed;
@ -283,7 +284,8 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
_recorded_non_young_free_cset_time_ms = time_ms;
}
void record_fast_reclaim_humongous_stats(size_t total, size_t candidates) {
void record_fast_reclaim_humongous_stats(double time_ms, size_t total, size_t candidates) {
_cur_fast_reclaim_humongous_register_time_ms = time_ms;
_cur_fast_reclaim_humongous_total = total;
_cur_fast_reclaim_humongous_candidates = candidates;
}

View File

@ -270,10 +270,14 @@
product(uintx, G1MixedGCCountTarget, 8, \
"The target number of mixed GCs after a marking cycle.") \
\
experimental(bool, G1ReclaimDeadHumongousObjectsAtYoungGC, true, \
experimental(bool, G1EagerReclaimHumongousObjects, true, \
"Try to reclaim dead large objects at every young GC.") \
\
experimental(bool, G1TraceReclaimDeadHumongousObjectsAtYoungGC, false, \
experimental(bool, G1EagerReclaimHumongousObjectsWithStaleRefs, true, \
"Try to reclaim dead large objects that have a few stale " \
"references at every young GC.") \
\
experimental(bool, G1TraceEagerReclaimHumongousObjects, false, \
"Print some information about large object liveness " \
"at every young GC.") \
\

View File

@ -681,6 +681,18 @@ void OtherRegionsTable::scrub(CardTableModRefBS* ctbs,
clear_fcc();
}
bool OtherRegionsTable::occupancy_less_or_equal_than(size_t limit) const {
if (limit <= (size_t)G1RSetSparseRegionEntries) {
return occ_coarse() == 0 && _first_all_fine_prts == NULL && occ_sparse() <= limit;
} else {
// Current uses of this method may only use values less than G1RSetSparseRegionEntries
// for the limit. The solution, comparing against occupied() would be too slow
// at this time.
Unimplemented();
return false;
}
}
bool OtherRegionsTable::is_empty() const {
return occ_sparse() == 0 && occ_coarse() == 0 && _first_all_fine_prts == NULL;
}

View File

@ -183,6 +183,10 @@ public:
// Returns whether the remembered set contains the given reference.
bool contains_reference(OopOrNarrowOopStar from) const;
// Returns whether this remembered set (and all sub-sets) have an occupancy
// that is less or equal than the given occupancy.
bool occupancy_less_or_equal_than(size_t limit) const;
// Removes any entries shown by the given bitmaps to contain only dead
// objects. Not thread safe.
// Set bits in the bitmaps indicate that the given region or card is live.
@ -261,6 +265,10 @@ public:
return (strong_code_roots_list_length() == 0) && _other_regions.is_empty();
}
bool occupancy_less_or_equal_than(size_t occ) const {
return (strong_code_roots_list_length() == 0) && _other_regions.occupancy_less_or_equal_than(occ);
}
size_t occupied() {
MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
return occupied_locked();

View File

@ -51,7 +51,7 @@ class FieldStreamBase : public StackObj {
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;

View File

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

View File

@ -39,6 +39,9 @@ const char* C2Compiler::retry_no_subsuming_loads() {
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 @@ void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
// 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;

View File

@ -47,6 +47,7 @@ public:
// 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();

View File

@ -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 @@ Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
}
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 @@ void ArrayCopyNode::dump_spec(outputStream *st) const {
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;
}

View File

@ -1070,8 +1070,8 @@ private:
// 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 @@ private:
// 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 @@ private:
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 @@ public:
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; }

View File

@ -774,7 +774,9 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
}
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);

View File

@ -4475,8 +4475,11 @@ void LibraryCallKit::copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, b
ArrayCopyNode* ac = ArrayCopyNode::make(this, false, src, NULL, dest, NULL, countx, false);
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 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
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 @@ bool LibraryCallKit::inline_arraycopy() {
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 @@ bool LibraryCallKit::inline_arraycopy() {
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 @@ bool LibraryCallKit::inline_arraycopy() {
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;
}

View File

@ -519,7 +519,8 @@ Node* PhaseMacroExpand::generate_arraycopy(ArrayCopyNode *ac, AllocateArrayNode*
// 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 @@ void PhaseMacroExpand::expand_arraycopy_node(ArrayCopyNode *ac) {
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 @@ void PhaseMacroExpand::expand_arraycopy_node(ArrayCopyNode *ac) {
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

View File

@ -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 @@ void Parse::do_exits() {
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);
}

View File

@ -1123,6 +1123,16 @@ WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean
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 @@ static JNINativeMethod methods[] = {
{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

View File

@ -145,6 +145,7 @@ needs_compact3 = \
gc/survivorAlignment \
runtime/InternalApi/ThreadCpuTimesDeadlock.java \
serviceability/threads/TestFalseDeadLock.java \
compiler/codecache/jmx
# Compact 2 adds full VM tests
compact2 = \
@ -413,6 +414,12 @@ hotspot_gc = \
gc/ \
-gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java
hotspot_gc_closed = \
sanity/ExecuteInternalVMTests.java
hotspot_gc_gcold = \
stress/gc/TestGCOld.java
hotspot_runtime = \
runtime/ \
-runtime/6888954/vmerrors.sh \
@ -444,6 +451,8 @@ hotspot_jprt = \
:hotspot_compiler_3 \
:hotspot_compiler_closed \
:hotspot_gc \
:hotspot_gc_closed \
:hotspot_gc_gcold \
:hotspot_runtime \
:hotspot_runtime_closed \
:hotspot_serviceability

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 7173584
* @summary arraycopy as macro node
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestArrayCopyMacro
*
*/
public class TestArrayCopyMacro {
static class A {
}
// In its own method so profiling reports both branches taken
static Object m2(Object o1, Object o2, int i) {
if (i == 4) {
return o1;
}
return o2;
}
static Object m1(A[] src, Object dest) {
int i = 1;
// won't be optimized out until after parsing
for (; i < 3; i *= 4) {
}
dest = m2(new A[10], dest, i);
// dest is new array here but C2 picks the "disjoint" stub
// only if stub to call is decided after parsing
System.arraycopy(src, 0, dest, 0, 10);
return dest;
}
public static void main(String[] args) {
A[] array_src = new A[10];
for (int i = 0; i < array_src.length; i++) {
array_src[i] = new A();
}
for (int i = 0; i < 20000; i++) {
m2(null, null, 0);
}
for (int i = 0; i < 20000; i++) {
Object[] array_dest = (Object[])m1(array_src, null);
for (int j = 0; j < array_src.length; j++) {
if (array_dest[j] != array_src[j]) {
throw new RuntimeException("copy failed at index " + j + " src = " + array_src[j] + " dest = " + array_dest[j]);
}
}
}
}
}

View File

@ -25,13 +25,13 @@
* @test
* @bug 8055910
* @summary Arrays.copyOf doesn't perform subtype check
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestArrayOfNoTypeCheck
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestArraysCopyOfNoTypeCheck
*
*/
import java.util.Arrays;
public class TestArrayOfNoTypeCheck {
public class TestArraysCopyOfNoTypeCheck {
static class A {
}

View File

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

View File

@ -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 @@ fi
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} ]

View File

@ -263,10 +263,10 @@ generate_replay() {
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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
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);
}
}
}
}

View File

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

View File

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

View File

@ -0,0 +1,129 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package common;
import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
import sun.hotspot.code.BlobType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
public class CodeCacheOptions {
public static final String SEGMENTED_CODE_CACHE = "SegmentedCodeCache";
private static final EnumSet<BlobType> NON_SEGMENTED_HEAPS
= EnumSet.of(BlobType.All);
private static final EnumSet<BlobType> ALL_SEGMENTED_HEAPS
= EnumSet.complementOf(NON_SEGMENTED_HEAPS);
private static final EnumSet<BlobType> SEGMENTED_HEAPS_WO_PROFILED
= EnumSet.of(BlobType.NonNMethod, BlobType.MethodNonProfiled);
private static final EnumSet<BlobType> ONLY_NON_METHODS_HEAP
= EnumSet.of(BlobType.NonNMethod);
public final long reserved;
public final long nonNmethods;
public final long nonProfiled;
public final long profiled;
public final boolean segmented;
public static long mB(long val) {
return CodeCacheOptions.kB(val) * 1024L;
}
public static long kB(long val) {
return val * 1024L;
}
public CodeCacheOptions(long reserved) {
this.reserved = reserved;
this.nonNmethods = 0;
this.nonProfiled = 0;
this.profiled = 0;
this.segmented = false;
}
public CodeCacheOptions(long reserved, long nonNmethods, long nonProfiled,
long profiled) {
this.reserved = reserved;
this.nonNmethods = nonNmethods;
this.nonProfiled = nonProfiled;
this.profiled = profiled;
this.segmented = true;
}
public long sizeForHeap(BlobType heap) {
switch (heap) {
case All:
return this.reserved;
case NonNMethod:
return this.nonNmethods;
case MethodNonProfiled:
return this.nonProfiled;
case MethodProfiled:
return this.profiled;
default:
throw new Error("Unknown heap: " + heap.name());
}
}
public String[] prepareOptions(String... additionalOptions) {
List<String> options = new ArrayList<>();
Collections.addAll(options, additionalOptions);
Collections.addAll(options,
CommandLineOptionTest.prepareBooleanFlag(
SEGMENTED_CODE_CACHE, segmented),
CommandLineOptionTest.prepareNumericFlag(
BlobType.All.sizeOptionName, reserved));
if (segmented) {
Collections.addAll(options,
CommandLineOptionTest.prepareNumericFlag(
BlobType.NonNMethod.sizeOptionName, nonNmethods),
CommandLineOptionTest.prepareNumericFlag(
BlobType.MethodNonProfiled.sizeOptionName,
nonProfiled),
CommandLineOptionTest.prepareNumericFlag(
BlobType.MethodProfiled.sizeOptionName, profiled));
}
return options.toArray(new String[options.size()]);
}
public CodeCacheOptions mapOptions(EnumSet<BlobType> involvedCodeHeaps) {
if (involvedCodeHeaps.isEmpty()
|| involvedCodeHeaps.equals(NON_SEGMENTED_HEAPS)
|| involvedCodeHeaps.equals(ALL_SEGMENTED_HEAPS)) {
return this;
} else if (involvedCodeHeaps.equals(SEGMENTED_HEAPS_WO_PROFILED)) {
return new CodeCacheOptions(reserved, nonNmethods,
profiled + nonProfiled, 0L);
} else if (involvedCodeHeaps.equals(ONLY_NON_METHODS_HEAP)) {
return new CodeCacheOptions(reserved, nonNmethods + profiled
+ nonProfiled, 0L, 0L);
} else {
throw new Error("Test bug: unexpected set of code heaps involved "
+ "into test.");
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import com.oracle.java.testlibrary.Asserts;
import java.lang.management.MemoryType;
import sun.hotspot.code.BlobType;
/**
* @test BeanTypeTest
* @library /testlibrary /../../test/lib
* @build BeanTypeTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache BeanTypeTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache BeanTypeTest
* @summary verify types of code cache memory pool bean
*/
public class BeanTypeTest {
public static void main(String args[]) {
for (BlobType bt : BlobType.getAvailable()) {
Asserts.assertEQ(MemoryType.NON_HEAP, bt.getMemoryPool().getType());
}
}
}

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import com.oracle.java.testlibrary.Utils;
import java.lang.management.MemoryPoolMXBean;
import javax.management.Notification;
import sun.hotspot.WhiteBox;
import sun.hotspot.code.BlobType;
import sun.hotspot.code.CodeBlob;
public final class CodeCacheUtils {
/**
* Returns the value to be used for code heap allocation
*/
public static final int ALLOCATION_SIZE
= Integer.getInteger("codecache.allocation.size", 100);
public static final WhiteBox WB = WhiteBox.getWhiteBox();
public static final long SEGMENT_SIZE
= WhiteBox.getWhiteBox().getUintxVMFlag("CodeCacheSegmentSize");
public static final long MIN_BLOCK_LENGTH
= WhiteBox.getWhiteBox().getUintxVMFlag("CodeCacheMinBlockLength");
public static final long MIN_ALLOCATION = SEGMENT_SIZE * MIN_BLOCK_LENGTH;
private CodeCacheUtils() {
// To prevent from instantiation
}
public static final void hitUsageThreshold(MemoryPoolMXBean bean,
BlobType btype) {
long initialSize = bean.getUsage().getUsed();
bean.setUsageThreshold(initialSize + 1);
long usageThresholdCount = bean.getUsageThresholdCount();
long addr = WB.allocateCodeBlob(1, btype.id);
WB.fullGC();
Utils.waitForCondition(()
-> bean.getUsageThresholdCount() == usageThresholdCount + 1);
WB.freeCodeBlob(addr);
}
public static final long getHeaderSize(BlobType btype) {
long addr = WB.allocateCodeBlob(0, btype.id);
int size = CodeBlob.getCodeBlob(addr).size;
WB.freeCodeBlob(addr);
return size;
}
public static String getPoolNameFromNotification(
Notification notification) {
return ((javax.management.openmbean.CompositeDataSupport)
notification.getUserData()).get("poolName").toString();
}
public static boolean isAvailableCodeHeapPoolName(String name) {
return BlobType.getAvailable().stream()
.map(BlobType::getMemoryPool)
.map(MemoryPoolMXBean::getName)
.filter(name::equals)
.findAny().isPresent();
}
/**
* A "non-nmethods" code heap is used by interpreter during bytecode
* execution, thus, it can't be predicted if this code heap usage will be
* increased or not. Same goes for 'All'.
*
* @param btype BlobType to be checked
* @return boolean value, true if respective code heap is predictable
*/
public static boolean isCodeHeapPredictable(BlobType btype) {
return btype == BlobType.MethodNonProfiled
|| btype == BlobType.MethodProfiled;
}
public static void disableCollectionUsageThresholds(){
BlobType.getAvailable().stream()
.map(BlobType::getMemoryPool)
.filter(MemoryPoolMXBean::isCollectionUsageThresholdSupported)
.forEach(b -> b.setCollectionUsageThreshold(0L));
}
}

View File

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

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import com.oracle.java.testlibrary.Asserts;
import java.lang.management.MemoryPoolMXBean;
import java.util.HashMap;
import java.util.Map;
import sun.hotspot.code.BlobType;
/*
* @test GetUsageTest
* @library /testlibrary /../../test/lib
* @build GetUsageTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:. -XX:CompileCommand=compileonly,null::*
* -XX:-UseCodeCacheFlushing -XX:-MethodFlushing -XX:+SegmentedCodeCache
* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI GetUsageTest
* @summary testing of getUsage() for segmented code cache
*/
public class GetUsageTest {
private final BlobType btype;
private final int allocateSize;
public GetUsageTest(BlobType btype, int allocSize) {
this.btype = btype;
this.allocateSize = allocSize;
}
public static void main(String[] args) throws Exception {
for (BlobType btype : BlobType.getAvailable()) {
if (CodeCacheUtils.isCodeHeapPredictable(btype)) {
for (int allocSize = 10; allocSize < 100000; allocSize *= 10) {
new GetUsageTest(btype, allocSize).runTest();
}
}
}
}
protected final Map<MemoryPoolMXBean, Long> getBeanUsages() {
Map<MemoryPoolMXBean, Long> beanUsages = new HashMap<>();
for (BlobType bt : BlobType.getAvailable()) {
beanUsages.put(bt.getMemoryPool(),
bt.getMemoryPool().getUsage().getUsed());
}
return beanUsages;
}
protected void runTest() {
MemoryPoolMXBean[] predictableBeans = BlobType.getAvailable().stream()
.filter(CodeCacheUtils::isCodeHeapPredictable)
.map(BlobType::getMemoryPool)
.toArray(MemoryPoolMXBean[]::new);
Map<MemoryPoolMXBean, Long> initial = getBeanUsages();
long addr = 0;
try {
addr = CodeCacheUtils.WB.allocateCodeBlob(allocateSize, btype.id);
Map<MemoryPoolMXBean, Long> current = getBeanUsages();
long blockCount = Math.floorDiv(allocateSize
+ CodeCacheUtils.getHeaderSize(btype)
+ CodeCacheUtils.SEGMENT_SIZE - 1, CodeCacheUtils.SEGMENT_SIZE);
long usageUpperEstimate = Math.max(blockCount,
CodeCacheUtils.MIN_BLOCK_LENGTH) * CodeCacheUtils.SEGMENT_SIZE;
for (MemoryPoolMXBean entry : predictableBeans) {
long diff = current.get(entry) - initial.get(entry);
if (entry.equals(btype.getMemoryPool())) {
Asserts.assertFalse(diff <= 0L || diff > usageUpperEstimate,
String.format("Pool %s usage increase was reported "
+ "unexpectedly as increased by %d using "
+ "allocation size %d", entry.getName(),
diff, allocateSize));
} else {
Asserts.assertEQ(diff, 0L,
String.format("Pool %s usage changed unexpectedly while"
+ " trying to increase: %s using allocation "
+ "size %d", entry.getName(),
btype.getMemoryPool().getName(), allocateSize));
}
}
} finally {
if (addr != 0) {
CodeCacheUtils.WB.freeCodeBlob(addr);
}
}
System.out.printf("INFO: Scenario finished successfully for %s%n",
btype.getMemoryPool().getName());
}
}

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import com.oracle.java.testlibrary.Asserts;
import java.lang.management.MemoryPoolMXBean;
import java.util.ArrayList;
import java.util.List;
import sun.hotspot.code.BlobType;
/*
* @test InitialAndMaxUsageTest
* @library /testlibrary /../../test/lib
* @build InitialAndMaxUsageTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:. -XX:-UseCodeCacheFlushing
* -XX:-MethodFlushing -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* -XX:+SegmentedCodeCache -XX:CompileCommand=compileonly,null::*
* InitialAndMaxUsageTest
* @summary testing of initial and max usage
*/
public class InitialAndMaxUsageTest {
private static final double CACHE_USAGE_COEF = 0.95d;
private final BlobType btype;
private final boolean lowerBoundIsZero;
private final long maxSize;
public InitialAndMaxUsageTest(BlobType btype) {
this.btype = btype;
this.maxSize = btype.getSize();
/* Only profiled code cache initial size should be 0, because of
-XX:CompileCommand=compileonly,null::* non-methods might be not empty,
as well as non-profiled methods, because it's used as fallback in
case non-methods is full */
lowerBoundIsZero = btype == BlobType.MethodProfiled;
}
public static void main(String[] args) {
for (BlobType btype : BlobType.getAvailable()) {
new InitialAndMaxUsageTest(btype).runTest();
}
}
private void fillWithSize(long size, List<Long> blobs) {
long blob;
while ((blob = CodeCacheUtils.WB.allocateCodeBlob(size, btype.id))
!= 0L) {
blobs.add(blob);
}
}
protected void runTest() {
long headerSize = CodeCacheUtils.getHeaderSize(btype);
MemoryPoolMXBean bean = btype.getMemoryPool();
long initialUsage = btype.getMemoryPool().getUsage().getUsed();
System.out.printf("INFO: trying to test %s of max size %d and initial"
+ " usage %d%n", bean.getName(), maxSize, initialUsage);
Asserts.assertLT(initialUsage + headerSize + 1L, maxSize,
"Initial usage is close to total size for " + bean.getName());
if (lowerBoundIsZero) {
Asserts.assertEQ(initialUsage, 0L, "Unexpected initial usage");
}
ArrayList<Long> blobs = new ArrayList<>();
long minAllocationUnit = CodeCacheUtils.MIN_ALLOCATION - headerSize;
/* now filling code cache with large-sized allocation first, since
lots of small allocations takes too much time, so, just a small
optimization */
try {
for (int coef = 1000000; coef > 0; coef /= 10) {
fillWithSize(coef * minAllocationUnit, blobs);
}
Asserts.assertGT((double) bean.getUsage().getUsed(),
CACHE_USAGE_COEF * maxSize, String.format("Unable to fill "
+ "more than %f of %s. Reported usage is %d ",
CACHE_USAGE_COEF, bean.getName(),
bean.getUsage().getUsed()));
} finally {
for (long entry : blobs) {
CodeCacheUtils.WB.freeCodeBlob(entry);
}
}
System.out.printf("INFO: Scenario finished successfully for %s%n",
bean.getName());
}
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import com.oracle.java.testlibrary.Asserts;
import java.lang.management.MemoryPoolMXBean;
import sun.hotspot.code.BlobType;
/**
* @test ManagerNamesTest
* @library /testlibrary /../../test/lib
* @build ManagerNamesTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache ManagerNamesTest
* * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache ManagerNamesTest
* @summary verify getMemoryManageNames calls in case of segmented code cache
*/
public class ManagerNamesTest {
private final MemoryPoolMXBean bean;
private final static String POOL_NAME = "CodeCacheManager";
public static void main(String args[]) {
for (BlobType btype : BlobType.getAvailable()) {
new ManagerNamesTest(btype).runTest();
}
}
public ManagerNamesTest(BlobType btype) {
bean = btype.getMemoryPool();
}
protected void runTest() {
String[] names = bean.getMemoryManagerNames();
Asserts.assertEQ(names.length, 1,
"Unexpected length of MemoryManagerNames");
Asserts.assertEQ(POOL_NAME, names[0],
"Unexpected value of MemoryManagerName");
System.out.printf("INFO: Scenario finished successfully for %s%n",
bean.getName());
}
}

View File

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

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import com.oracle.java.testlibrary.Asserts;
import java.lang.management.MemoryPoolMXBean;
import sun.hotspot.code.BlobType;
/*
* @test PeakUsageTest
* @library /testlibrary /../../test/lib
* @build PeakUsageTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache
* -XX:CompileCommand=compileonly,null::* PeakUsageTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache
* -XX:CompileCommand=compileonly,null::* PeakUsageTest
* @summary testing of getPeakUsage() and resetPeakUsage for
* segmented code cache
*/
public class PeakUsageTest {
private final BlobType btype;
public PeakUsageTest(BlobType btype) {
this.btype = btype;
}
public static void main(String[] args) {
for (BlobType btype : BlobType.getAvailable()) {
if (CodeCacheUtils.isCodeHeapPredictable(btype)) {
new PeakUsageTest(btype).runTest();
}
}
}
protected void runTest() {
MemoryPoolMXBean bean = btype.getMemoryPool();
bean.resetPeakUsage();
long addr = CodeCacheUtils.WB.allocateCodeBlob(
CodeCacheUtils.ALLOCATION_SIZE, btype.id);
long newPeakUsage = bean.getPeakUsage().getUsed();
try {
Asserts.assertEQ(newPeakUsage, bean.getUsage().getUsed(),
"Peak usage does not match usage after allocation for "
+ bean.getName());
} finally {
if (addr != 0) {
CodeCacheUtils.WB.freeCodeBlob(addr);
}
}
Asserts.assertEQ(newPeakUsage, bean.getPeakUsage().getUsed(),
"Code cache peak usage has changed after usage decreased for "
+ bean.getName());
bean.resetPeakUsage();
Asserts.assertEQ(bean.getPeakUsage().getUsed(),
bean.getUsage().getUsed(),
"Code cache peak usage is not equal to usage after reset for "
+ bean.getName());
long addr2 = CodeCacheUtils.WB.allocateCodeBlob(
CodeCacheUtils.ALLOCATION_SIZE, btype.id);
try {
Asserts.assertEQ(bean.getPeakUsage().getUsed(),
bean.getUsage().getUsed(),
"Code cache peak usage is not equal to usage after fresh "
+ "allocation for " + bean.getName());
} finally {
if (addr2 != 0) {
CodeCacheUtils.WB.freeCodeBlob(addr2);
}
}
System.out.printf("INFO: Scenario finished successfully for %s%n",
bean.getName());
}
}

View File

@ -0,0 +1,131 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import com.oracle.java.testlibrary.Asserts;
import com.oracle.java.testlibrary.Utils;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryNotificationInfo;
import java.lang.management.MemoryPoolMXBean;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import javax.management.ListenerNotFoundException;
import javax.management.Notification;
import javax.management.NotificationEmitter;
import javax.management.NotificationListener;
import sun.hotspot.code.BlobType;
/*
* @test PoolsIndependenceTest
* @library /testlibrary /../../test/lib
* @build PoolsIndependenceTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:. -XX:-UseCodeCacheFlushing
* -XX:-MethodFlushing -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* -XX:+SegmentedCodeCache PoolsIndependenceTest
* @summary testing of getUsageThreshold()
*/
public class PoolsIndependenceTest implements NotificationListener {
private final Map<String, AtomicInteger> counters;
private final BlobType btype;
private volatile long lastEventTimestamp;
public PoolsIndependenceTest(BlobType btype) {
counters = new HashMap<>();
for (BlobType bt : BlobType.getAvailable()) {
counters.put(bt.getMemoryPool().getName(), new AtomicInteger(0));
}
this.btype = btype;
lastEventTimestamp = 0;
CodeCacheUtils.disableCollectionUsageThresholds();
}
public static void main(String[] args) {
for (BlobType bt : BlobType.getAvailable()) {
new PoolsIndependenceTest(bt).runTest();
}
}
protected void runTest() {
MemoryPoolMXBean bean = btype.getMemoryPool();
((NotificationEmitter) ManagementFactory.getMemoryMXBean()).
addNotificationListener(this, null, null);
bean.setUsageThreshold(bean.getUsage().getUsed() + 1);
long beginTimestamp = System.currentTimeMillis();
CodeCacheUtils.WB.allocateCodeBlob(
CodeCacheUtils.ALLOCATION_SIZE, btype.id);
CodeCacheUtils.WB.fullGC();
/* waiting for expected event to be received plus double the time took
to receive expected event(for possible unexpected) and
plus 1 second in case expected event received (almost)immediately */
Utils.waitForCondition(() -> {
long currentTimestamp = System.currentTimeMillis();
int eventsCount
= counters.get(btype.getMemoryPool().getName()).get();
if (eventsCount > 0) {
if (eventsCount > 1) {
return true;
}
long timeLastEventTook
= beginTimestamp - lastEventTimestamp;
long timeoutValue
= 1000L + beginTimestamp + 3L * timeLastEventTook;
return currentTimestamp > timeoutValue;
}
return false;
});
for (BlobType bt : BlobType.getAvailable()) {
int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0;
Asserts.assertEQ(counters.get(bt.getMemoryPool().getName()).get(),
expectedNotificationsAmount, String.format("Unexpected "
+ "amount of notifications for pool: %s",
bt.getMemoryPool().getName()));
}
try {
((NotificationEmitter) ManagementFactory.getMemoryMXBean()).
removeNotificationListener(this);
} catch (ListenerNotFoundException ex) {
throw new AssertionError("Can't remove notification listener", ex);
}
System.out.printf("INFO: Scenario with %s finished%n", bean.getName());
}
@Override
public void handleNotification(Notification notification, Object handback) {
String nType = notification.getType();
String poolName
= CodeCacheUtils.getPoolNameFromNotification(notification);
// consider code cache events only
if (CodeCacheUtils.isAvailableCodeHeapPoolName(poolName)) {
Asserts.assertEQ(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED,
nType, "Unexpected event received: " + nType);
// receiving events from available CodeCache-related beans only
if (counters.get(poolName) != null) {
counters.get(poolName).incrementAndGet();
lastEventTimestamp = System.currentTimeMillis();
}
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -127,10 +127,7 @@ public class TestRTMAbortRatio extends CommandLineOptionTest {
@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 class TestRTMAbortRatio extends CommandLineOptionTest {
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);
}
}

View File

@ -157,10 +157,7 @@ public class TestRTMAfterNonRTMDeopt extends CommandLineOptionTest {
@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 class TestRTMAfterNonRTMDeopt extends CommandLineOptionTest {
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 {

View File

@ -130,10 +130,7 @@ public class TestRTMDeoptOnLowAbortRatio extends CommandLineOptionTest {
@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 class TestRTMDeoptOnLowAbortRatio extends CommandLineOptionTest {
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);
}

View File

@ -143,10 +143,7 @@ public class TestRTMLockingThreshold extends CommandLineOptionTest {
@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 class TestRTMLockingThreshold extends CommandLineOptionTest {
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);
}
}

View File

@ -117,9 +117,7 @@ public class TestRTMTotalCountIncrRate extends CommandLineOptionTest {
@Override
public String[] getMethodsToCompileNames() {
return new String[] {
getMethodWithLockName()
};
return new String[] { getMethodWithLockName() };
}
public void lock() {
@ -135,11 +133,13 @@ public class TestRTMTotalCountIncrRate extends CommandLineOptionTest {
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();
}
}

View File

@ -52,7 +52,7 @@ import rtm.predicate.SupportedVM;
* 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 class TestUseRTMAfterLockInflation extends CommandLineOptionTest {
}
public static class Test {
/**
* Usage:
* Test &lt;provoker type&gt;
@ -113,10 +112,12 @@ public class TestUseRTMAfterLockInflation extends CommandLineOptionTest {
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();
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import com.oracle.java.testlibrary.Asserts;
import com.oracle.java.testlibrary.Platform;
import java.util.stream.IntStream;
import sun.hotspot.WhiteBox;
public class CompilerUtils {
private CompilerUtils() {
// to prevent from instantiation
}
/**
* Returns available compilation levels
*
* @return int array with compilation levels
*/
public static int[] getAvailableCompilationLevels() {
if (!WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompiler")) {
return new int[0];
}
if (WhiteBox.getWhiteBox().getBooleanVMFlag("TieredCompilation")) {
Long flagValue = WhiteBox.getWhiteBox()
.getIntxVMFlag("TieredStopAtLevel");
int maxLevel = flagValue.intValue();
Asserts.assertEQ(new Long(maxLevel), flagValue,
"TieredStopAtLevel has value out of int capacity");
return IntStream.rangeClosed(1, maxLevel).toArray();
} else {
if (Platform.isServer()) {
return new int[]{4};
}
if (Platform.isClient() || Platform.isMinimal()) {
return new int[]{1};
}
}
return new int[0];
}
}

View File

@ -29,8 +29,7 @@ import java.util.concurrent.BrokenBarrierException;
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 @@ import sun.misc.Unsafe;
*/
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 @@ public abstract class AbortProvoker implements CompilableTest {
* @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 @@ public abstract class AbortProvoker implements CompilableTest {
}
for (long i = 0; i < iterations; i++) {
AbortProvoker.verifyMonitorState(provoker, monitorShouldBeInflated);
provoker.forceAbort();
}
}

View File

@ -77,7 +77,7 @@ public class BusyLock implements CompilableTest, Runnable {
}
}
public void test() {
public void syncAndTest() {
try {
barrier.await();
// wait until monitor is locked by a ::run method
@ -85,6 +85,10 @@ public class BusyLock implements CompilableTest, Runnable {
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException("Synchronization error happened.", e);
}
test();
}
public void test() {
synchronized(monitor) {
BusyLock.field++;
}
@ -130,7 +134,7 @@ public class BusyLock implements CompilableTest, Runnable {
Thread t = new Thread(busyLock);
t.start();
busyLock.test();
busyLock.syncAndTest();
t.join();
}
}

View File

@ -69,11 +69,6 @@ class MemoryConflictProvoker extends AbortProvoker {
* 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 @@ class MemoryConflictProvoker extends AbortProvoker {
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) {

View File

@ -240,7 +240,8 @@ public class RTMTestBase {
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()) {

View File

@ -22,7 +22,7 @@
*/
/*
* @test TestEagerReclaimHumongousRegions2
* @test TestEagerReclaimHumongousRegionsClearMarkBits
* @bug 8051973
* @summary Test to make sure that eager reclaim of humongous objects correctly clears
* mark bitmaps at reclaim.
@ -109,7 +109,7 @@ class ReclaimRegionFast {
}
}
public class TestEagerReclaimHumongousRegions2 {
public class TestEagerReclaimHumongousRegionsClearMarkBits {
public static void main(String[] args) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:+UseG1GC",

View File

@ -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.
*/
/*
* @test TestEagerReclaimHumongousRegionsWithRefs
* @bug 8048179
* @summary Test to make sure that eager reclaim of humongous objects that have previously
* been referenced by other old gen regions work. We simply try to fill
* up the heap with humongous objects and create a remembered set entry from an object by
* referencing that we know is in the old gen. After changing this reference, the object
* should still be eagerly reclaimable to avoid Full GC.
* @key gc
* @library /testlibrary
*/
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.LinkedList;
import com.oracle.java.testlibrary.OutputAnalyzer;
import com.oracle.java.testlibrary.ProcessTools;
import static com.oracle.java.testlibrary.Asserts.*;
class RefHolder {
Object ref;
}
class ReclaimRegionFast {
public static final int M = 1024*1024;
public static LinkedList<Object> garbageList = new LinkedList<Object>();
public static void genGarbage() {
for (int i = 0; i < 32*1024; i++) {
garbageList.add(new int[100]);
}
garbageList.clear();
}
// A large object referenced by a static.
static int[] filler = new int[10 * M];
// Old gen object referencing the large object, generating remembered
// set entries.
static RefHolder fromOld = new RefHolder();
public static void main(String[] args) {
int[] large = new int[M];
Object ref_from_stack = large;
for (int i = 0; i < 100; i++) {
// A large object that will be reclaimed eagerly.
large = new int[6*M];
fromOld.ref = large;
genGarbage();
}
// Keep the reference to the first object alive.
System.out.println(ref_from_stack);
}
}
public class TestEagerReclaimHumongousRegionsWithRefs {
public static void main(String[] args) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:+UseG1GC",
"-Xms128M",
"-Xmx128M",
"-Xmn16M",
"-XX:+PrintGC",
ReclaimRegionFast.class.getName());
Pattern p = Pattern.compile("Full GC");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
int found = 0;
Matcher m = p.matcher(output.getStdout());
while (m.find()) {
found++;
}
System.out.println("Issued " + found + " Full GCs");
assertLessThan(found, 10, "Found that " + found + " Full GCs were issued. This is larger than the bound. Eager reclaim of objects once referenced from old gen seems to not work at all");
output.shouldHaveExitValue(0);
}
}

View File

@ -22,9 +22,9 @@
*/
/*
* @test TestG1TraceReclaimDeadHumongousObjectsAtYoungGC
* @bug 8058801
* @summary Ensure that the output for a G1TraceReclaimDeadHumongousObjectsAtYoungGC
* @test TestG1TraceEagerReclaimHumongousObjects
* @bug 8058801 8048179
* @summary Ensure that the output for a G1TraceEagerReclaimHumongousObjects
* includes the expected necessary messages.
* @key gc
* @library /testlibrary
@ -34,7 +34,7 @@ import com.oracle.java.testlibrary.ProcessTools;
import com.oracle.java.testlibrary.OutputAnalyzer;
import java.util.LinkedList;
public class TestG1TraceReclaimDeadHumongousObjectsAtYoungGC {
public class TestG1TraceEagerReclaimHumongousObjects {
public static void main(String[] args) throws Exception {
testGCLogs();
testHumongousObjectGCLogs();
@ -50,12 +50,12 @@ public class TestG1TraceReclaimDeadHumongousObjectsAtYoungGC {
"-XX:+PrintGC",
"-XX:+UnlockExperimentalVMOptions",
"-XX:G1LogLevel=finest",
"-XX:+G1TraceReclaimDeadHumongousObjectsAtYoungGC",
"-XX:+G1TraceEagerReclaimHumongousObjects",
GCTest.class.getName());
OutputAnalyzer output = new OutputAnalyzer(pb.start());
// As G1ReclaimDeadHumongousObjectsAtYoungGC is set(default), below logs should be displayed.
// As G1EagerReclaimHumongousObjects is set(default), below logs should be displayed.
// And GCTest doesn't have humongous objects, so values should be zero.
output.shouldContain("[Humongous Reclaim");
output.shouldContain("[Humongous Total: 0]");
@ -74,7 +74,7 @@ public class TestG1TraceReclaimDeadHumongousObjectsAtYoungGC {
"-XX:+PrintGC",
"-XX:+UnlockExperimentalVMOptions",
"-XX:G1LogLevel=finest",
"-XX:+G1TraceReclaimDeadHumongousObjectsAtYoungGC",
"-XX:+G1TraceEagerReclaimHumongousObjects",
GCWithHumongousObjectTest.class.getName());
OutputAnalyzer output = new OutputAnalyzer(pb.start());
@ -88,7 +88,7 @@ public class TestG1TraceReclaimDeadHumongousObjectsAtYoungGC {
// As G1TraceReclaimDeadHumongousObjectsAtYoungGC is set and GCWithHumongousObjectTest has humongous objects,
// these logs should be displayed.
output.shouldContain("Live humongous");
output.shouldContain("Reclaim humongous region");
output.shouldContain("Dead humongous region");
output.shouldHaveExitValue(0);
}

View File

@ -23,7 +23,7 @@
/*
* @test TestGCLogMessages
* @bug 8035406 8027295 8035398 8019342 8027959
* @bug 8035406 8027295 8035398 8019342 8027959 8048179
* @summary Ensure that the PrintGCDetails output for a minor GC with G1
* includes the expected necessary messages.
* @key gc
@ -54,6 +54,7 @@ public class TestGCLogMessages {
output.shouldNotContain("[String Dedup Fixup");
output.shouldNotContain("[Young Free CSet");
output.shouldNotContain("[Non-Young Free CSet");
output.shouldNotContain("[Humongous Register");
output.shouldNotContain("[Humongous Reclaim");
output.shouldHaveExitValue(0);
@ -72,9 +73,10 @@ public class TestGCLogMessages {
output.shouldContain("[String Dedup Fixup");
output.shouldNotContain("[Young Free CSet");
output.shouldNotContain("[Non-Young Free CSet");
output.shouldContain("[Humongous Reclaim");
output.shouldContain("[Humongous Register");
output.shouldNotContain("[Humongous Total");
output.shouldNotContain("[Humongous Candidate");
output.shouldContain("[Humongous Reclaim");
output.shouldNotContain("[Humongous Reclaimed");
output.shouldHaveExitValue(0);
@ -95,9 +97,10 @@ public class TestGCLogMessages {
output.shouldContain("[String Dedup Fixup");
output.shouldContain("[Young Free CSet");
output.shouldContain("[Non-Young Free CSet");
output.shouldContain("[Humongous Reclaim");
output.shouldContain("[Humongous Register");
output.shouldContain("[Humongous Total");
output.shouldContain("[Humongous Candidate");
output.shouldContain("[Humongous Reclaim");
output.shouldContain("[Humongous Reclaimed");
output.shouldHaveExitValue(0);
}

View File

@ -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.
*/
import com.oracle.java.testlibrary.*;
/*
* @test TestNullTerminatedFlags
* @bug 6522873
* @summary Test that the VM don't allow random junk characters at the end of valid command line flags.
* @library /testlibrary
* @run driver TestNullTerminatedFlags
*/
public class TestNullTerminatedFlags {
public static String[] options = {
"-Xnoclassgc",
"-Xconcgc",
"-Xnoconcgc",
"-Xbatch",
"-green",
"-native",
"-Xsqnopause",
"-Xrs",
"-Xusealtsigs",
"-Xoptimize",
"-Xprof",
"-Xconcurrentio",
"-Xinternalversion",
"-Xprintflags",
"-Xint",
"-Xmixed",
"-Xcomp",
"-Xshare:dump",
"-Xshare:on",
"-Xshare:auto",
"-Xshare:off",
"-Xdebug",
"-Xnoagent",
"-Xboundthreads"
};
public static void main(String args[]) throws Exception{
for (String option : options) {
String testOption = option + "junk";
ProcessBuilder pb =
ProcessTools.createJavaProcessBuilder(testOption, "-version");
new OutputAnalyzer(pb.start())
.shouldContain("Unrecognized option: " + testOption)
.shouldHaveExitValue(1);
}
}
}

View File

@ -0,0 +1,417 @@
/*
* 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 TestGCOld
* @key gc
* @key stress
* @requires vm.gc=="null"
* @summary Stress the GC by trying to make old objects more likely to be garbage than young objects.
* @run main/othervm -Xmx384M -XX:+UseSerialGC TestGCOld 50 1 20 10 10000
* @run main/othervm -Xmx384M -XX:+UseParallelGC TestGCOld 50 1 20 10 10000
* @run main/othervm -Xmx384M -XX:+UseParallelGC -XX:-UseParallelOldGC TestGCOld 50 1 20 10 10000
* @run main/othervm -Xmx384M -XX:+UseConcMarkSweepGC TestGCOld 50 1 20 10 10000
* @run main/othervm -Xmx384M -XX:+UseG1GC TestGCOld 50 1 20 10 10000
*/
import java.text.*;
import java.util.Random;
class TreeNode {
public TreeNode left, right;
public int val; // will always be the height of the tree
}
/* Args:
live-data-size: in megabytes (approximate, will be rounded down).
work: units of mutator non-allocation work per byte allocated,
(in unspecified units. This will affect the promotion rate
printed at the end of the run: more mutator work per step implies
fewer steps per second implies fewer bytes promoted per second.)
short/long ratio: ratio of short-lived bytes allocated to long-lived
bytes allocated.
pointer mutation rate: number of pointer mutations per step.
steps: number of steps to do.
*/
public class TestGCOld {
// Command-line parameters.
private static int size, workUnits, promoteRate, ptrMutRate, steps;
// Constants.
private static final int MEG = 1000000;
private static final int INSIGNIFICANT = 999; // this many bytes don't matter
private static final int BYTES_PER_WORD = 4;
private static final int BYTES_PER_NODE = 20; // bytes per TreeNode
private static final int WORDS_DEAD = 100; // size of young garbage object
private final static int treeHeight = 14;
private final static long treeSize = heightToBytes(treeHeight);
private static final String msg1
= "Usage: java TestGCOld <size> <work> <ratio> <mutation> <steps>";
private static final String msg2
= " where <size> is the live storage in megabytes";
private static final String msg3
= " <work> is the mutator work per step (arbitrary units)";
private static final String msg4
= " <ratio> is the ratio of short-lived to long-lived allocation";
private static final String msg5
= " <mutation> is the mutations per step";
private static final String msg6
= " <steps> is the number of steps";
// Counters (and global variables that discourage optimization)
private static long youngBytes = 0; // total young bytes allocated
private static long nodes = 0; // total tree nodes allocated
private static long actuallyMut = 0; // pointer mutations in old trees
private static long mutatorSum = 0; // checksum to discourage optimization
public static int[] aexport; // exported array to discourage opt
// Global variables.
private static TreeNode[] trees;
private static int where = 0; // roving index into trees
private static Random rnd = new Random();
// Returns the height of the given tree.
private static int height (TreeNode t) {
if (t == null) {
return 0;
}
else {
return 1 + Math.max (height (t.left), height (t.right));
}
}
// Returns the length of the shortest path in the given tree.
private static int shortestPath (TreeNode t) {
if (t == null) {
return 0;
}
else {
return 1 + Math.min (shortestPath (t.left), shortestPath (t.right));
}
}
// Returns the number of nodes in a balanced tree of the given height.
private static long heightToNodes (int h) {
if (h == 0) {
return 0;
}
else {
long n = 1;
while (h > 1) {
n = n + n;
h = h - 1;
}
return n + n - 1;
}
}
// Returns the number of bytes in a balanced tree of the given height.
private static long heightToBytes (int h) {
return BYTES_PER_NODE * heightToNodes (h);
}
// Returns the height of the largest balanced tree
// that has no more than the given number of nodes.
private static int nodesToHeight (long nodes) {
int h = 1;
long n = 1;
while (n + n - 1 <= nodes) {
n = n + n;
h = h + 1;
}
return h - 1;
}
// Returns the height of the largest balanced tree
// that occupies no more than the given number of bytes.
private static int bytesToHeight (long bytes) {
return nodesToHeight (bytes / BYTES_PER_NODE);
}
// Returns a newly allocated balanced binary tree of height h.
private static TreeNode makeTree(int h) {
if (h == 0) return null;
else {
TreeNode res = new TreeNode();
nodes++;
res.left = makeTree(h-1);
res.right = makeTree(h-1);
res.val = h;
return res;
}
}
// Allocates approximately size megabytes of trees and stores
// them into a global array.
private static void init() {
int ntrees = (int) ((size * MEG) / treeSize);
trees = new TreeNode[ntrees];
System.err.println("Allocating " + ntrees + " trees.");
System.err.println(" (" + (ntrees * treeSize) + " bytes)");
for (int i = 0; i < ntrees; i++) {
trees[i] = makeTree(treeHeight);
// doYoungGenAlloc(promoteRate*ntrees*treeSize, WORDS_DEAD);
}
System.err.println(" (" + nodes + " nodes)");
/* Allow any in-progress GC to catch up... */
// try { Thread.sleep(20000); } catch (InterruptedException x) {}
}
// Confirms that all trees are balanced and have the correct height.
private static void checkTrees() {
int ntrees = trees.length;
for (int i = 0; i < ntrees; i++) {
TreeNode t = trees[i];
int h1 = height(t);
int h2 = shortestPath(t);
if ((h1 != treeHeight) || (h2 != treeHeight)) {
System.err.println("*****BUG: " + h1 + " " + h2);
}
}
}
// Called only by replaceTree (below) and by itself.
private static void replaceTreeWork(TreeNode full, TreeNode partial, boolean dir) {
boolean canGoLeft = full.left != null && full.left.val > partial.val;
boolean canGoRight = full.right != null && full.right.val > partial.val;
if (canGoLeft && canGoRight) {
if (dir)
replaceTreeWork(full.left, partial, !dir);
else
replaceTreeWork(full.right, partial, !dir);
} else if (!canGoLeft && !canGoRight) {
if (dir)
full.left = partial;
else
full.right = partial;
} else if (!canGoLeft) {
full.left = partial;
} else {
full.right = partial;
}
}
// Given a balanced tree full and a smaller balanced tree partial,
// replaces an appropriate subtree of full by partial, taking care
// to preserve the shape of the full tree.
private static void replaceTree(TreeNode full, TreeNode partial) {
boolean dir = (partial.val % 2) == 0;
actuallyMut++;
replaceTreeWork(full, partial, dir);
}
// Allocates approximately n bytes of long-lived storage,
// replacing oldest existing long-lived storage.
private static void oldGenAlloc(long n) {
int full = (int) (n / treeSize);
long partial = n % treeSize;
// System.out.println("In oldGenAlloc, doing " + full + " full trees "
// + "and one partial tree of size " + partial);
for (int i = 0; i < full; i++) {
trees[where++] = makeTree(treeHeight);
if (where == trees.length) where = 0;
}
while (partial > INSIGNIFICANT) {
int h = bytesToHeight(partial);
TreeNode newTree = makeTree(h);
replaceTree(trees[where++], newTree);
if (where == trees.length) where = 0;
partial = partial - heightToBytes(h);
}
}
// Interchanges two randomly selected subtrees (of same size and depth).
private static void oldGenSwapSubtrees() {
// Randomly pick:
// * two tree indices
// * A depth
// * A path to that depth.
int index1 = rnd.nextInt(trees.length);
int index2 = rnd.nextInt(trees.length);
int depth = rnd.nextInt(treeHeight);
int path = rnd.nextInt();
TreeNode tn1 = trees[index1];
TreeNode tn2 = trees[index2];
for (int i = 0; i < depth; i++) {
if ((path & 1) == 0) {
tn1 = tn1.left;
tn2 = tn2.left;
} else {
tn1 = tn1.right;
tn2 = tn2.right;
}
path >>= 1;
}
TreeNode tmp;
if ((path & 1) == 0) {
tmp = tn1.left;
tn1.left = tn2.left;
tn2.left = tmp;
} else {
tmp = tn1.right;
tn1.right = tn2.right;
tn2.right = tmp;
}
actuallyMut += 2;
}
// Update "n" old-generation pointers.
private static void oldGenMut(long n) {
for (int i = 0; i < n/2; i++) {
oldGenSwapSubtrees();
}
}
// Does the amount of mutator work appropriate for n bytes of young-gen
// garbage allocation.
private static void doMutWork(long n) {
int sum = 0;
long limit = workUnits*n/10;
for (long k = 0; k < limit; k++) sum++;
// We don't want dead code elimination to eliminate the loop above.
mutatorSum = mutatorSum + sum;
}
// Allocate n bytes of young-gen garbage, in units of "nwords"
// words.
private static void doYoungGenAlloc(long n, int nwords) {
final int nbytes = nwords*BYTES_PER_WORD;
int allocated = 0;
while (allocated < n) {
aexport = new int[nwords];
/* System.err.println("Step"); */
allocated += nbytes;
}
youngBytes = youngBytes + allocated;
}
// Allocate "n" bytes of young-gen data; and do the
// corresponding amount of old-gen allocation and pointer
// mutation.
// oldGenAlloc may perform some mutations, so this code
// takes those mutations into account.
private static void doStep(long n) {
long mutations = actuallyMut;
doYoungGenAlloc(n, WORDS_DEAD);
doMutWork(n);
oldGenAlloc(n / promoteRate);
oldGenMut(Math.max(0L, (mutations + ptrMutRate) - actuallyMut));
}
public static void main(String[] args) {
if (args.length != 5) {
System.err.println(msg1);
System.err.println(msg2);
System.err.println(msg3);
System.err.println(msg4);
System.err.println(msg5);
System.err.println(msg6);
return;
}
size = Integer.parseInt(args[0]);
workUnits = Integer.parseInt(args[1]);
promoteRate = Integer.parseInt(args[2]);
ptrMutRate = Integer.parseInt(args[3]);
steps = Integer.parseInt(args[4]);
System.out.println(size + " megabytes of live storage");
System.out.println(workUnits + " work units per step");
System.out.println("promotion ratio is 1:" + promoteRate);
System.out.println("pointer mutation rate is " + ptrMutRate);
System.out.println(steps + " steps");
init();
// checkTrees();
youngBytes = 0;
nodes = 0;
System.err.println("Initialization complete...");
long start = System.currentTimeMillis();
for (int step = 0; step < steps; step++) {
doStep(MEG);
}
long end = System.currentTimeMillis();
float secs = ((float)(end-start))/1000.0F;
// checkTrees();
NumberFormat nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(1);
System.out.println("\nTook " + nf.format(secs) + " sec in steady state.");
nf.setMaximumFractionDigits(2);
System.out.println("Allocated " + steps + " Mb of young gen garbage"
+ " (= " + nf.format(((float)steps)/secs) +
" Mb/sec)");
System.out.println(" (actually allocated " +
nf.format(((float) youngBytes)/MEG) + " megabytes)");
float promoted = ((float)steps) / (float)promoteRate;
System.out.println("Promoted " + promoted +
" Mb (= " + nf.format(promoted/secs) + " Mb/sec)");
System.out.println(" (actually promoted " +
nf.format(((float) (nodes * BYTES_PER_NODE))/MEG) +
" megabytes)");
if (ptrMutRate != 0) {
System.out.println("Mutated " + actuallyMut +
" pointers (= " +
nf.format(actuallyMut/secs) + " ptrs/sec)");
}
// This output serves mainly to discourage optimization.
System.out.println("Checksum = " + (mutatorSum + aexport.length));
}
}

View File

@ -37,6 +37,7 @@ import java.security.SecureClassLoader;
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
@ -50,6 +51,21 @@ public class ByteCodeLoader extends SecureClassLoader {
this.byteCode = byteCode;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (!name.equals(className)) {
return super.loadClass(name);
}
if (holder == null) {
synchronized(this) {
if (holder == null) {
holder = findClass(name);
}
}
}
return holder;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
if (!name.equals(className)) {

View File

@ -54,7 +54,9 @@ public class InfiniteLoop implements Runnable {
try {
while (true) {
target.run();
Thread.sleep(mills);
if (mills > 0) {
Thread.sleep(mills);
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();

View File

@ -34,6 +34,7 @@ public class Platform {
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 @@ public class Platform {
return vmName.contains("Embedded");
}
public static boolean isTieredSupported() {
return compiler.contains("Tiered Compilers");
}
public static boolean is32bit() {
return dataModel.equals("32");
}

View File

@ -40,6 +40,7 @@ import java.util.Arrays;
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;
@ -305,25 +306,6 @@ public final class Utils {
}
}
/**
* Returns file content as a list of strings
*
* @param file File to operate on
* @return List of strings
* @throws IOException
*/
public static List<String> fileAsList(File file) throws IOException {
assertTrue(file.exists() && file.isFile(),
file.getAbsolutePath() + " does not exist or not a file");
List<String> output = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader(file.getAbsolutePath()))) {
while (reader.ready()) {
output.add(reader.readLine().replace(NEW_LINE, ""));
}
}
return output;
}
/**
* Return the contents of the named file as a single String,
* or null if not found.
@ -395,6 +377,52 @@ public final class Utils {
return RANDOM_GENERATOR;
}
/**
* Wait for condition to be true
*
* @param condition, a condition to wait for
*/
public static final void waitForCondition(BooleanSupplier condition) {
waitForCondition(condition, -1L, 100L);
}
/**
* Wait until timeout for condition to be true
*
* @param condition, a condition to wait for
* @param timeout a time in milliseconds to wait for condition to be true
* specifying -1 will wait forever
* @return condition value, to determine if wait was successfull
*/
public static final boolean waitForCondition(BooleanSupplier condition,
long timeout) {
return waitForCondition(condition, timeout, 100L);
}
/**
* Wait until timeout for condition to be true for specified time
*
* @param condition, a condition to wait for
* @param timeout a time in milliseconds to wait for condition to be true,
* specifying -1 will wait forever
* @param sleepTime a time to sleep value in milliseconds
* @return condition value, to determine if wait was successfull
*/
public static final boolean waitForCondition(BooleanSupplier condition,
long timeout, long sleepTime) {
long startTime = System.currentTimeMillis();
while (!(condition.getAsBoolean() || (timeout != -1L
&& ((System.currentTimeMillis() - startTime) > timeout)))) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new Error(e);
}
}
return condition.getAsBoolean();
}
/**
* Adjusts the provided timeout value for the TIMEOUT_FACTOR
* @param tOut the timeout value to be adjusted

View File

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

View File

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

View File

@ -1,5 +0,0 @@
public class Bar {
private static void staticMethod() { }
public void method() { }
protected Bar() { }
}

View File

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

View File

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

View File

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

View File

@ -1,5 +0,0 @@
public class Foo {
private static void staticMethod() { }
public void method() { }
protected Foo() { }
}

View File

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

View File

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

View File

@ -1,4 +0,0 @@
java.lang.String
java.lang.Object
Foo
Bar

View File

@ -48,7 +48,7 @@ public class TestMutuallyExclusivePlatformPredicates {
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;

View File

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

View File

@ -285,3 +285,5 @@ a12d347f84176200593999f4da91ae2bb86865b2 jdk9-b39
3f46e2196498de33e7c65efa7b372e46f1faba01 jdk9-b40
71dd8f7649428efd3a56ca5fefc80e59d37b8434 jdk9-b41
47b0d3fa4118b9d56870cf4004987438c501f5c0 jdk9-b42
40b242363040229a05224fbc5dc203a3f46a8f8f jdk9-b43
0cb0844b58924d6086d2850c22087d06679d5eef jdk9-b44

325
jaxp/test/Makefile Normal file
View File

@ -0,0 +1,325 @@
#
# Copyright (c) 1995, 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. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# 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.
#
#
# Makefile to run various JAXP tests
#
.DEFAULT : all
# Empty these to get rid of some default rules
.SUFFIXES:
.SUFFIXES: .java
CO=
GET=
# Utilities used
AWK = awk
CAT = cat
CD = cd
CHMOD = chmod
CP = cp
CUT = cut
DIRNAME = dirname
ECHO = echo
EGREP = egrep
EXPAND = expand
FIND = find
MKDIR = mkdir
PWD = pwd
SED = sed
SORT = sort
TEE = tee
UNAME = uname
UNIQ = uniq
WC = wc
ZIP = zip
# Get OS name from uname (Cygwin inexplicably adds _NT-5.1)
UNAME_S := $(shell $(UNAME) -s | $(CUT) -f1 -d_)
# Commands to run on paths to make mixed paths for java on windows
ifeq ($(UNAME_S), CYGWIN)
# Location of developer shared files
SLASH_JAVA = J:
GETMIXEDPATH = cygpath -m
else
# Location of developer shared files
SLASH_JAVA = /java
GETMIXEDPATH=$(ECHO)
endif
# Root of this test area (important to use full paths in some places)
TEST_ROOT := $(shell $(PWD))
# Root of all test results
ifdef ALT_OUTPUTDIR
ABS_OUTPUTDIR = $(shell $(CD) $(ALT_OUTPUTDIR) && $(PWD))
else
ABS_OUTPUTDIR = $(shell $(CD) $(TEST_ROOT)/.. && $(PWD))
endif
ABS_PLATFORM_BUILD_ROOT = $(ABS_OUTPUTDIR)
ABS_TEST_OUTPUT_DIR := $(ABS_PLATFORM_BUILD_ROOT)/testoutput/$(UNIQUE_DIR)
# Expect JPRT to set PRODUCT_HOME (the product or jdk in this case to test)
ifndef PRODUCT_HOME
# Try to use j2sdk-image if it exists
ABS_JDK_IMAGE = $(ABS_PLATFORM_BUILD_ROOT)/images/j2sdk-image
PRODUCT_HOME := \
$(shell \
if [ -d $(ABS_JDK_IMAGE) ] ; then \
$(ECHO) "$(ABS_JDK_IMAGE)"; \
else \
$(ECHO) "$(ABS_PLATFORM_BUILD_ROOT)"; \
fi)
PRODUCT_HOME := $(PRODUCT_HOME)
endif
# Expect JPRT to set JPRT_PRODUCT_ARGS (e.g. -server etc.)
# Should be passed into 'java' only.
# Could include: -d64 -server -client OR any java option
ifdef JPRT_PRODUCT_ARGS
JAVA_ARGS = $(JPRT_PRODUCT_ARGS)
endif
# Expect JPRT to set JPRT_PRODUCT_VM_ARGS (e.g. -Xcomp etc.)
# Should be passed into anything running the vm (java, javac, javadoc, ...).
ifdef JPRT_PRODUCT_VM_ARGS
JAVA_VM_ARGS = $(JPRT_PRODUCT_VM_ARGS)
endif
# Expect JPRT to set JPRT_ARCHIVE_BUNDLE (path to zip bundle for results)
ifdef JPRT_ARCHIVE_BUNDLE
ARCHIVE_BUNDLE = $(JPRT_ARCHIVE_BUNDLE)
else
ARCHIVE_BUNDLE = $(ABS_TEST_OUTPUT_DIR)/ARCHIVE_BUNDLE.zip
endif
# How to create the test bundle (pass or fail, we want to create this)
# Follow command with ";$(BUNDLE_UP_AND_EXIT)", so it always gets executed.
ZIP_UP_RESULTS = ( $(MKDIR) -p `$(DIRNAME) $(ARCHIVE_BUNDLE)` \
&& $(CD) $(ABS_TEST_OUTPUT_DIR) \
&& $(CHMOD) -R a+r . \
&& $(ZIP) -q -r $(ARCHIVE_BUNDLE) . )
# important results files
SUMMARY_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/JTreport/text/summary.txt")
STATS_TXT_NAME = Stats.txt
STATS_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/$(STATS_TXT_NAME)")
RUNLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/runlist.txt")
PASSLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/passlist.txt")
FAILLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/faillist.txt")
EXITCODE = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/exitcode.txt")
TESTEXIT = \
if [ ! -s $(EXITCODE) ] ; then \
$(ECHO) "ERROR: EXITCODE file not filled in."; \
$(ECHO) "1" > $(EXITCODE); \
fi ; \
testExitCode=`$(CAT) $(EXITCODE)`; \
$(ECHO) "EXIT CODE: $${testExitCode}"; \
exit $${testExitCode}
BUNDLE_UP_AND_EXIT = \
( \
jtregExitCode=$$? && \
_summary="$(SUMMARY_TXT)"; \
$(RM) -f $(STATS_TXT) $(RUNLIST) $(PASSLIST) $(FAILLIST) $(EXITCODE); \
$(ECHO) "$${jtregExitCode}" > $(EXITCODE); \
if [ -r "$${_summary}" ] ; then \
$(ECHO) "Summary: $(UNIQUE_DIR)" > $(STATS_TXT); \
$(EXPAND) $${_summary} | $(EGREP) -v ' Not run\.' > $(RUNLIST); \
$(EGREP) ' Passed\.' $(RUNLIST) \
| $(EGREP) -v ' Error\.' \
| $(EGREP) -v ' Failed\.' > $(PASSLIST); \
( $(EGREP) ' Failed\.' $(RUNLIST); \
$(EGREP) ' Error\.' $(RUNLIST); \
$(EGREP) -v ' Passed\.' $(RUNLIST) ) \
| $(SORT) | $(UNIQ) > $(FAILLIST); \
if [ $${jtregExitCode} != 0 -o -s $(FAILLIST) ] ; then \
$(EXPAND) $(FAILLIST) \
| $(CUT) -d' ' -f1 \
| $(SED) -e 's@^@FAILED: @' >> $(STATS_TXT); \
if [ $${jtregExitCode} = 0 ] ; then \
jtregExitCode=1; \
fi; \
fi; \
runc="`$(CAT) $(RUNLIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \
passc="`$(CAT) $(PASSLIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \
failc="`$(CAT) $(FAILLIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \
exclc="FIXME CODETOOLS-7900176"; \
$(ECHO) "TEST STATS: name=$(UNIQUE_DIR) run=$${runc} pass=$${passc} fail=$${failc}" \
>> $(STATS_TXT); \
else \
$(ECHO) "Missing file: $${_summary}" >> $(STATS_TXT); \
fi; \
if [ -f $(STATS_TXT) ] ; then \
$(CAT) $(STATS_TXT); \
fi; \
$(ZIP_UP_RESULTS) ; \
$(TESTEXIT) \
)
################################################################
# Default make rule (runs default JAXP tests)
all: jaxp_all
@$(ECHO) "Testing completed successfully"
# Prep for output
# Change execute permissions on shared library files.
# Files in repositories should never have execute permissions, but
# there are some tests that have pre-built shared libraries, and these
# windows dll files must have execute permission. Adding execute
# permission may happen automatically on windows when using certain
# versions of mercurial but it cannot be guaranteed. And blindly
# adding execute permission might be seen as a mercurial 'change', so
# we avoid adding execute permission to repository files. But testing
# from a plain source tree needs the chmod a+rx. Applying the chmod to
# all shared libraries not just dll files. And with CYGWIN and sshd
# service, you may need CYGWIN=ntsec for this to work.
prep:
@$(MKDIR) -p $(ABS_TEST_OUTPUT_DIR)
@$(MKDIR) -p `$(DIRNAME) $(ARCHIVE_BUNDLE)`
@if [ ! -d $(TEST_ROOT)/../.hg ] ; then \
$(FIND) $(TEST_ROOT) \( -name \*.dll -o -name \*.DLL -o -name \*.so \) \
-exec $(CHMOD) a+rx {} \; ; \
fi
# Cleanup
clean:
@$(RM) -r $(ABS_TEST_OUTPUT_DIR)
@$(RM) $(ARCHIVE_BUNDLE)
################################################################
# jtreg tests
# Expect JT_HOME to be set for jtreg tests. (home for jtreg)
ifndef JT_HOME
JT_HOME = $(SLASH_JAVA)/re/jtreg/4.1/promoted/latest/binaries/jtreg
ifdef JPRT_JTREG_HOME
JT_HOME = $(JPRT_JTREG_HOME)
endif
endif
# Problematic tests to be excluded
PROBLEM_LISTS=$(call MixedDirs,$(wildcard ProblemList.txt closed/ProblemList.txt))
# Create exclude list for this platform and arch
ifdef NO_EXCLUDES
JTREG_EXCLUSIONS =
else
JTREG_EXCLUSIONS = $(PROBLEM_LISTS:%=-exclude:%)
endif
# convert list of directories to dos paths
define MixedDirs
$(foreach i,$1,$(shell $(GETMIXEDPATH) "${i}"))
endef
define SummaryInfo
$(ECHO) "########################################################"
$(CAT) $(?:%=$(ABS_TEST_OUTPUT_DIR)/%/$(STATS_TXT_NAME))
$(ECHO) "########################################################"
endef
# ------------------------------------------------------------------
jaxp_%:
$(ECHO) "Running tests: $@"
for each in $@; do \
$(MAKE) -j 1 TEST_SELECTION=":$$each" UNIQUE_DIR=$$each jtreg_tests; \
done
# ------------------------------------------------------------------
ifdef CONCURRENCY
EXTRA_JTREG_OPTIONS += -concurrency:$(CONCURRENCY)
endif
# Default JTREG to run (win32 script works for everybody)
JTREG = $(JT_HOME)/win32/bin/jtreg
# run in agentvm mode
JTREG_BASIC_OPTIONS += -agentvm
# Only run automatic tests
JTREG_BASIC_OPTIONS += -a
# Always turn on assertions
JTREG_ASSERT_OPTION = -ea -esa
JTREG_BASIC_OPTIONS += $(JTREG_ASSERT_OPTION)
# Report details on all failed or error tests, times too
JTREG_BASIC_OPTIONS += -v:fail,error,time
# Retain all files for failing tests
JTREG_BASIC_OPTIONS += -retain:fail,error
# Ignore tests are not run and completely silent about it
JTREG_IGNORE_OPTION = -ignore:quiet
JTREG_BASIC_OPTIONS += $(JTREG_IGNORE_OPTION)
# Multiple by 4 the timeout numbers
JTREG_TIMEOUT_OPTION = -timeoutFactor:4
JTREG_BASIC_OPTIONS += $(JTREG_TIMEOUT_OPTION)
# Set the max memory for jtreg control vm
JTREG_MEMORY_OPTION = -J-Xmx512m
JTREG_BASIC_OPTIONS += $(JTREG_MEMORY_OPTION)
# Add any extra options
JTREG_BASIC_OPTIONS += $(EXTRA_JTREG_OPTIONS)
# Set other vm and test options
JTREG_TEST_OPTIONS = $(JAVA_ARGS:%=-javaoptions:%) $(JAVA_VM_ARGS:%=-vmoption:%)
# Set the GC options for test vms
#JTREG_GC_OPTION = -vmoption:-XX:+UseSerialGC
#JTREG_TEST_OPTIONS += $(JTREG_GC_OPTION)
# Set the max memory for jtreg target test vms
JTREG_TESTVM_MEMORY_OPTION = -vmoption:-Xmx512m
JTREG_TEST_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION)
# Make sure jtreg exists
$(JTREG): $(JT_HOME)
# Run jtreg
jtreg_tests: prep $(PRODUCT_HOME) $(JTREG)
( \
( JT_HOME=$(shell $(GETMIXEDPATH) "$(JT_HOME)"); \
export JT_HOME; \
$(shell $(GETMIXEDPATH) "$(JTREG)") \
$(JTREG_BASIC_OPTIONS) \
-r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/JTreport") \
-w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/JTwork") \
-jdk:$(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)") \
$(JTREG_EXCLUSIONS) \
$(JTREG_TEST_OPTIONS) \
$(TEST_SELECTION) \
) ; \
$(BUNDLE_UP_AND_EXIT) \
) 2>&1 | $(TEE) $(ABS_TEST_OUTPUT_DIR)/output.txt ; $(TESTEXIT)
PHONY_LIST += jtreg_tests
################################################################
# Phony targets (e.g. these are not filenames)
.PHONY: all clean prep $(PHONY_LIST)
################################################################

View File

@ -2,5 +2,7 @@
# It also contains test-suite configuration information.
# Tests that must run in othervm mode
othervm.dirs=javax/xml/jaxp/unittest
othervm.dirs=javax/xml/jaxp
# Group definitions
groups=TEST.groups

24
jaxp/test/TEST.groups Normal file
View File

@ -0,0 +1,24 @@
# 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.
#
jaxp_all = \
javax/xml/jaxp

View File

@ -288,3 +288,5 @@ dd4ba422dba858b1c3c4b38f49a3e514be4e2790 jdk9-b38
5455969de31f3083bcfd779b7acc3ab758ecb308 jdk9-b40
4f785187377fe4c7ff388a7026dd72fcccdcfe7a jdk9-b41
301ddb4478fb36d1f025d14e7e48c2a434e9e6ff jdk9-b42
edc13d27dc871be57d7ca77eef77e6d04972fee2 jdk9-b43
2a03baa4d849818ff6d635f110c2813b12fc2326 jdk9-b44

Some files were not shown because too many files have changed in this diff Show More