This commit is contained in:
Alejandro Murillo 2016-07-15 09:05:33 -07:00
commit 84a55fcca8
71 changed files with 1489 additions and 672 deletions

View File

@ -51,6 +51,7 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \
$(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \
$(HOTSPOT_TOPDIR)/test/compiler/calls \
$(HOTSPOT_TOPDIR)/test/compiler/native \
$(HOTSPOT_TOPDIR)/test/serviceability/jvmti/GetNamedModule \
$(HOTSPOT_TOPDIR)/test/testlibrary/jvmti \
#
@ -64,6 +65,7 @@ endif
ifeq ($(TOOLCHAIN_TYPE), solstudio)
BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_liboverflow := -lc
BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libSimpleClassFileLoadHook := -lc
BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libGetNamedModuleTest := -lc
endif
BUILD_HOTSPOT_JTREG_OUTPUT_DIR := $(BUILD_OUTPUT)/support/test/hotspot/jtreg/native

View File

@ -1742,11 +1742,11 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
}
typedef struct {
Elf32_Half code; // Actual value as defined in elf.h
Elf32_Half compat_class; // Compatibility of archs at VM's sense
char elf_class; // 32 or 64 bit
char endianess; // MSB or LSB
char* name; // String representation
Elf32_Half code; // Actual value as defined in elf.h
Elf32_Half compat_class; // Compatibility of archs at VM's sense
unsigned char elf_class; // 32 or 64 bit
unsigned char endianess; // MSB or LSB
char* name; // String representation
} arch_t;
#ifndef EM_486

View File

@ -1320,36 +1320,8 @@ bool os::getTimesSecs(double* process_real_time,
}
bool os::supports_vtime() { return true; }
bool os::enable_vtime() {
int fd = ::open("/proc/self/ctl", O_WRONLY);
if (fd == -1) {
return false;
}
long cmd[] = { PCSET, PR_MSACCT };
int res = ::write(fd, cmd, sizeof(long) * 2);
::close(fd);
if (res != sizeof(long) * 2) {
return false;
}
return true;
}
bool os::vtime_enabled() {
int fd = ::open("/proc/self/status", O_RDONLY);
if (fd == -1) {
return false;
}
pstatus_t status;
int res = os::read(fd, (void*) &status, sizeof(pstatus_t));
::close(fd);
if (res != sizeof(pstatus_t)) {
return false;
}
return status.pr_flags & PR_MSACCT;
}
bool os::enable_vtime() { return false; }
bool os::vtime_enabled() { return false; }
double os::elapsedVTime() {
return (double)gethrvtime() / (double)hrtime_hz;

View File

@ -224,7 +224,7 @@ static const jchar ONE_CHAR[] = { (jchar) 0x8180};
static const jbyte THREE_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82};
static const jbyte FOUR_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82, (jbyte) 0x83};
static const jchar TWO_CHAR[] = { (jchar) 0x8180, (jchar) 0x8382};
static const jint ONE_INT[] = { 0x83828180};
static const jint ONE_INT[] = { (jint)0x83828180};
static const jbyte SIX_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82, (jbyte) 0x83, (jbyte) 0x84, (jbyte) 0x85};
static const jchar THREE_CHAR[] = { (jchar) 0x8180, (jchar) 0x8382, (jchar) 0x8584};
static const jbyte EIGHT_BYTE[] = {
@ -235,7 +235,7 @@ static const jchar FOUR_CHAR[] = {
(jchar) 0x8180, (jchar) 0x8382,
(jchar) 0x8584, (jchar) 0x8786};
static const jint TWO_INT[] = { 0x83828180, 0x87868584};
static const jint TWO_INT[] = { (jint)0x83828180, (jint)0x87868584};
static const juint MURMUR3_32_X86_CHECK_VALUE = 0xB0F57EE3;

View File

@ -142,7 +142,9 @@ void ClassLoaderData::oops_do(OopClosure* f, KlassClosure* klass_closure, bool m
f->do_oop(&_class_loader);
_dependencies.oops_do(f);
_handles->oops_do(f);
if (_handles != NULL) {
_handles->oops_do(f);
}
if (klass_closure != NULL) {
classes_do(klass_closure);
}

View File

@ -871,12 +871,17 @@ void java_lang_Class::fixup_module_field(KlassHandle k, Handle module) {
int java_lang_Class::oop_size(oop java_class) {
assert(_oop_size_offset != 0, "must be set");
return java_class->int_field(_oop_size_offset);
int size = java_class->int_field(_oop_size_offset);
assert(size > 0, "Oop size must be greater than zero, not %d", size);
return size;
}
void java_lang_Class::set_oop_size(oop java_class, int size) {
assert(_oop_size_offset != 0, "must be set");
assert(size > 0, "Oop size must be greater than zero, not %d", size);
java_class->int_field_put(_oop_size_offset, size);
}
int java_lang_Class::static_oop_field_count(oop java_class) {
assert(_static_oop_field_count_offset != 0, "must be set");
return java_class->int_field(_static_oop_field_count_offset);

View File

@ -275,7 +275,6 @@ class java_lang_Class : AllStatic {
static int static_oop_field_count(oop java_class);
static void set_static_oop_field_count(oop java_class, int size);
static GrowableArray<Klass*>* fixup_mirror_list() {
return _fixup_mirror_list;
}

View File

@ -820,6 +820,28 @@ jobject Modules::get_module_by_package_name(jobject loader, jstring package, TRA
}
jobject Modules::get_named_module(Handle h_loader, const char* package_str, TRAPS) {
assert(ModuleEntryTable::javabase_defined(),
"Attempt to call get_named_module before java.base is defined");
assert(h_loader.is_null() || java_lang_ClassLoader::is_subclass(h_loader->klass()),
"Class loader is not a subclass of java.lang.ClassLoader");
assert(package_str != NULL, "the package_str should not be NULL");
if (strlen(package_str) == 0) {
return NULL;
}
TempNewSymbol package_sym = SymbolTable::new_symbol(package_str, CHECK_NULL);
const PackageEntry* const pkg_entry =
get_package_entry_by_name(package_sym, h_loader, THREAD);
const ModuleEntry* const module_entry = (pkg_entry != NULL ? pkg_entry->module() : NULL);
if (module_entry != NULL && module_entry->module() != NULL && module_entry->is_named()) {
return JNIHandles::make_local(THREAD, JNIHandles::resolve(module_entry->module()));
}
return NULL;
}
// This method is called by JFR and by the above method.
jobject Modules::get_module(Symbol* package_name, Handle h_loader, TRAPS) {
const PackageEntry* const pkg_entry =

View File

@ -121,6 +121,7 @@ public:
// IllegalArgumentException is thrown if loader is neither null nor a subtype of
// java/lang/ClassLoader.
static jobject get_module_by_package_name(jobject loader, jstring package, TRAPS);
static jobject get_named_module(Handle h_loader, const char* package, TRAPS);
// If package is defined by loader, return the
// java.lang.reflect.Module object for the module in which the package is defined.

View File

@ -1256,9 +1256,7 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc,
// set between the last GC or pause and now. We need to clear the
// incremental collection set and then start rebuilding it afresh
// after this full GC.
abandon_collection_set(collection_set()->inc_head());
collection_set()->clear_incremental();
collection_set()->stop_incremental_building();
abandon_collection_set(collection_set());
tear_down_region_sets(false /* free_list_only */);
collector_state()->set_gcs_are_young(true);
@ -1379,7 +1377,6 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc,
_verifier->check_bitmaps("Full GC End");
// Start a new incremental collection set for the next pause
assert(collection_set()->head() == NULL, "must be");
collection_set()->start_incremental_building();
clear_cset_fast_test();
@ -1724,8 +1721,6 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* collector_policy) :
_old_marking_cycles_started(0),
_old_marking_cycles_completed(0),
_in_cset_fast_test(),
_worker_cset_start_region(NULL),
_worker_cset_start_region_time_stamp(NULL),
_gc_timer_stw(new (ResourceObj::C_HEAP, mtGC) STWGCTimer()),
_gc_tracer_stw(new (ResourceObj::C_HEAP, mtGC) G1NewTracer()) {
@ -1748,8 +1743,6 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* collector_policy) :
uint n_queues = ParallelGCThreads;
_task_queues = new RefToScanQueueSet(n_queues);
_worker_cset_start_region = NEW_C_HEAP_ARRAY(HeapRegion*, n_queues, mtGC);
_worker_cset_start_region_time_stamp = NEW_C_HEAP_ARRAY(uint, n_queues, mtGC);
_evacuation_failed_info_array = NEW_C_HEAP_ARRAY(EvacuationFailedInfo, n_queues, mtGC);
for (uint i = 0; i < n_queues; i++) {
@ -1758,7 +1751,6 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* collector_policy) :
_task_queues->register_queue(i, q);
::new (&_evacuation_failed_info_array[i]) EvacuationFailedInfo();
}
clear_cset_start_regions();
// Initialize the G1EvacuationFailureALot counters and flags.
NOT_PRODUCT(reset_evacuation_should_fail();)
@ -1987,6 +1979,8 @@ jint G1CollectedHeap::initialize() {
_preserved_marks_set.init(ParallelGCThreads);
_collection_set.initialize(max_regions());
return JNI_OK;
}
@ -2420,117 +2414,12 @@ G1CollectedHeap::heap_region_par_iterate(HeapRegionClosure* cl,
_hrm.par_iterate(cl, worker_id, hrclaimer, concurrent);
}
// Clear the cached CSet starting regions and (more importantly)
// the time stamps. Called when we reset the GC time stamp.
void G1CollectedHeap::clear_cset_start_regions() {
assert(_worker_cset_start_region != NULL, "sanity");
assert(_worker_cset_start_region_time_stamp != NULL, "sanity");
for (uint i = 0; i < ParallelGCThreads; i++) {
_worker_cset_start_region[i] = NULL;
_worker_cset_start_region_time_stamp[i] = 0;
}
}
// Given the id of a worker, obtain or calculate a suitable
// starting region for iterating over the current collection set.
HeapRegion* G1CollectedHeap::start_cset_region_for_worker(uint worker_i) {
assert(get_gc_time_stamp() > 0, "should have been updated by now");
HeapRegion* result = NULL;
unsigned gc_time_stamp = get_gc_time_stamp();
if (_worker_cset_start_region_time_stamp[worker_i] == gc_time_stamp) {
// Cached starting region for current worker was set
// during the current pause - so it's valid.
// Note: the cached starting heap region may be NULL
// (when the collection set is empty).
result = _worker_cset_start_region[worker_i];
assert(result == NULL || result->in_collection_set(), "sanity");
return result;
}
// The cached entry was not valid so let's calculate
// a suitable starting heap region for this worker.
// We want the parallel threads to start their collection
// set iteration at different collection set regions to
// avoid contention.
// If we have:
// n collection set regions
// p threads
// Then thread t will start at region floor ((t * n) / p)
result = collection_set()->head();
uint cs_size = collection_set()->region_length();
uint active_workers = workers()->active_workers();
uint end_ind = (cs_size * worker_i) / active_workers;
uint start_ind = 0;
if (worker_i > 0 &&
_worker_cset_start_region_time_stamp[worker_i - 1] == gc_time_stamp) {
// Previous workers starting region is valid
// so let's iterate from there
start_ind = (cs_size * (worker_i - 1)) / active_workers;
OrderAccess::loadload();
result = _worker_cset_start_region[worker_i - 1];
}
for (uint i = start_ind; i < end_ind; i++) {
result = result->next_in_collection_set();
}
// Note: the calculated starting heap region may be NULL
// (when the collection set is empty).
assert(result == NULL || result->in_collection_set(), "sanity");
assert(_worker_cset_start_region_time_stamp[worker_i] != gc_time_stamp,
"should be updated only once per pause");
_worker_cset_start_region[worker_i] = result;
OrderAccess::storestore();
_worker_cset_start_region_time_stamp[worker_i] = gc_time_stamp;
return result;
}
void G1CollectedHeap::collection_set_iterate(HeapRegionClosure* cl) {
HeapRegion* r = collection_set()->head();
while (r != NULL) {
HeapRegion* next = r->next_in_collection_set();
if (cl->doHeapRegion(r)) {
cl->incomplete();
return;
}
r = next;
}
_collection_set.iterate(cl);
}
void G1CollectedHeap::collection_set_iterate_from(HeapRegion* r,
HeapRegionClosure *cl) {
if (r == NULL) {
// The CSet is empty so there's nothing to do.
return;
}
assert(r->in_collection_set(),
"Start region must be a member of the collection set.");
HeapRegion* cur = r;
while (cur != NULL) {
HeapRegion* next = cur->next_in_collection_set();
if (cl->doHeapRegion(cur) && false) {
cl->incomplete();
return;
}
cur = next;
}
cur = collection_set()->head();
while (cur != r) {
HeapRegion* next = cur->next_in_collection_set();
if (cl->doHeapRegion(cur) && false) {
cl->incomplete();
return;
}
cur = next;
}
void G1CollectedHeap::collection_set_iterate_from(HeapRegionClosure *cl, uint worker_id) {
_collection_set.iterate_from(cl, worker_id, workers()->active_workers());
}
HeapRegion* G1CollectedHeap::next_compaction_region(const HeapRegion* from) const {
@ -3090,6 +2979,18 @@ void G1CollectedHeap::wait_for_root_region_scanning() {
g1_policy()->phase_times()->record_root_region_scan_wait_time(wait_time_ms);
}
class G1PrintCollectionSetClosure : public HeapRegionClosure {
private:
G1HRPrinter* _hr_printer;
public:
G1PrintCollectionSetClosure(G1HRPrinter* hr_printer) : HeapRegionClosure(), _hr_printer(hr_printer) { }
virtual bool doHeapRegion(HeapRegion* r) {
_hr_printer->cset(r);
return false;
}
};
bool
G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
assert_at_safepoint(true /* should_be_vm_thread */);
@ -3268,11 +3169,8 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
_cm->verify_no_cset_oops();
if (_hr_printer.is_active()) {
HeapRegion* hr = collection_set()->head();
while (hr != NULL) {
_hr_printer.cset(hr);
hr = hr->next_in_collection_set();
}
G1PrintCollectionSetClosure cl(&_hr_printer);
_collection_set.iterate(&cl);
}
// Initialize the GC alloc regions.
@ -3287,12 +3185,10 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
post_evacuate_collection_set(evacuation_info, &per_thread_states);
const size_t* surviving_young_words = per_thread_states.surviving_young_words();
free_collection_set(collection_set()->head(), evacuation_info, surviving_young_words);
free_collection_set(&_collection_set, evacuation_info, surviving_young_words);
eagerly_reclaim_humongous_regions();
collection_set()->clear_head();
record_obj_copy_mem_stats();
_survivor_evac_stats.adjust_desired_plab_sz();
_old_evac_stats.adjust_desired_plab_sz();
@ -4704,120 +4600,139 @@ void G1CollectedHeap::scrub_rem_set() {
workers()->run_task(&g1_par_scrub_rs_task);
}
void G1CollectedHeap::free_collection_set(HeapRegion* cs_head, EvacuationInfo& evacuation_info, const size_t* surviving_young_words) {
size_t pre_used = 0;
FreeRegionList local_free_list("Local List for CSet Freeing");
class G1FreeCollectionSetClosure : public HeapRegionClosure {
private:
const size_t* _surviving_young_words;
double young_time_ms = 0.0;
double non_young_time_ms = 0.0;
FreeRegionList _local_free_list;
size_t _rs_lengths;
// Bytes used in successfully evacuated regions before the evacuation.
size_t _before_used_bytes;
// Bytes used in unsucessfully evacuated regions before the evacuation
size_t _after_used_bytes;
_eden.clear();
size_t _bytes_allocated_in_old_since_last_gc;
G1Policy* policy = g1_policy();
size_t _failure_used_words;
size_t _failure_waste_words;
double start_sec = os::elapsedTime();
bool non_young = true;
double _young_time;
double _non_young_time;
public:
G1FreeCollectionSetClosure(const size_t* surviving_young_words) :
HeapRegionClosure(),
_surviving_young_words(surviving_young_words),
_local_free_list("Local Region List for CSet Freeing"),
_rs_lengths(0),
_before_used_bytes(0),
_after_used_bytes(0),
_bytes_allocated_in_old_since_last_gc(0),
_failure_used_words(0),
_failure_waste_words(0),
_young_time(0.0),
_non_young_time(0.0) {
}
HeapRegion* cur = cs_head;
int age_bound = -1;
size_t rs_lengths = 0;
virtual bool doHeapRegion(HeapRegion* r) {
double start_time = os::elapsedTime();
while (cur != NULL) {
assert(!is_on_master_free_list(cur), "sanity");
if (non_young) {
if (cur->is_young()) {
double end_sec = os::elapsedTime();
double elapsed_ms = (end_sec - start_sec) * 1000.0;
non_young_time_ms += elapsed_ms;
bool is_young = r->is_young();
start_sec = os::elapsedTime();
non_young = false;
}
G1CollectedHeap* g1h = G1CollectedHeap::heap();
assert(!g1h->is_on_master_free_list(r), "sanity");
_rs_lengths += r->rem_set()->occupied_locked();
assert(r->in_collection_set(), "Region %u should be in collection set.", r->hrm_index());
g1h->clear_in_cset(r);
if (is_young) {
int index = r->young_index_in_cset();
assert(index != -1, "Young index in collection set must not be -1 for region %u", r->hrm_index());
assert((uint) index < g1h->collection_set()->young_region_length(), "invariant");
size_t words_survived = _surviving_young_words[index];
r->record_surv_words_in_group(words_survived);
} else {
if (!cur->is_young()) {
double end_sec = os::elapsedTime();
double elapsed_ms = (end_sec - start_sec) * 1000.0;
young_time_ms += elapsed_ms;
start_sec = os::elapsedTime();
non_young = true;
}
assert(r->young_index_in_cset() == -1, "Young index for old region %u in collection set must be -1", r->hrm_index());
}
rs_lengths += cur->rem_set()->occupied_locked();
HeapRegion* next = cur->next_in_collection_set();
assert(cur->in_collection_set(), "bad CS");
cur->set_next_in_collection_set(NULL);
clear_in_cset(cur);
if (cur->is_young()) {
int index = cur->young_index_in_cset();
assert(index != -1, "invariant");
assert((uint) index < collection_set()->young_region_length(), "invariant");
size_t words_survived = surviving_young_words[index];
cur->record_surv_words_in_group(words_survived);
if (!r->evacuation_failed()) {
assert(r->not_empty(), "Region %u is an empty region in the collection set.", r->hrm_index());
_before_used_bytes += r->used();
g1h->free_region(r, &_local_free_list, false /* par */, true /* locked */);
} else {
int index = cur->young_index_in_cset();
assert(index == -1, "invariant");
}
assert( (cur->is_young() && cur->young_index_in_cset() > -1) ||
(!cur->is_young() && cur->young_index_in_cset() == -1),
"invariant" );
if (!cur->evacuation_failed()) {
MemRegion used_mr = cur->used_region();
// And the region is empty.
assert(!used_mr.is_empty(), "Should not have empty regions in a CS.");
pre_used += cur->used();
free_region(cur, &local_free_list, false /* par */, true /* locked */);
} else {
cur->uninstall_surv_rate_group();
if (cur->is_young()) {
cur->set_young_index_in_cset(-1);
}
cur->set_evacuation_failed(false);
r->uninstall_surv_rate_group();
r->set_young_index_in_cset(-1);
r->set_evacuation_failed(false);
// When moving a young gen region to old gen, we "allocate" that whole region
// there. This is in addition to any already evacuated objects. Notify the
// policy about that.
// Old gen regions do not cause an additional allocation: both the objects
// still in the region and the ones already moved are accounted for elsewhere.
if (cur->is_young()) {
policy->add_bytes_allocated_in_old_since_last_gc(HeapRegion::GrainBytes);
if (is_young) {
_bytes_allocated_in_old_since_last_gc += HeapRegion::GrainBytes;
}
// The region is now considered to be old.
cur->set_old();
r->set_old();
// Do some allocation statistics accounting. Regions that failed evacuation
// are always made old, so there is no need to update anything in the young
// gen statistics, but we need to update old gen statistics.
size_t used_words = cur->marked_bytes() / HeapWordSize;
_old_evac_stats.add_failure_used_and_waste(used_words, HeapRegion::GrainWords - used_words);
_old_set.add(cur);
evacuation_info.increment_collectionset_used_after(cur->used());
size_t used_words = r->marked_bytes() / HeapWordSize;
_failure_used_words += used_words;
_failure_waste_words += HeapRegion::GrainWords - used_words;
g1h->old_set_add(r);
_after_used_bytes += r->used();
}
cur = next;
if (is_young) {
_young_time += os::elapsedTime() - start_time;
} else {
_non_young_time += os::elapsedTime() - start_time;
}
return false;
}
evacuation_info.set_regions_freed(local_free_list.length());
policy->record_max_rs_lengths(rs_lengths);
FreeRegionList* local_free_list() { return &_local_free_list; }
size_t rs_lengths() const { return _rs_lengths; }
size_t before_used_bytes() const { return _before_used_bytes; }
size_t after_used_bytes() const { return _after_used_bytes; }
size_t bytes_allocated_in_old_since_last_gc() const { return _bytes_allocated_in_old_since_last_gc; }
size_t failure_used_words() const { return _failure_used_words; }
size_t failure_waste_words() const { return _failure_waste_words; }
double young_time() const { return _young_time; }
double non_young_time() const { return _non_young_time; }
};
void G1CollectedHeap::free_collection_set(G1CollectionSet* collection_set, EvacuationInfo& evacuation_info, const size_t* surviving_young_words) {
_eden.clear();
G1FreeCollectionSetClosure cl(surviving_young_words);
collection_set_iterate(&cl);
evacuation_info.set_regions_freed(cl.local_free_list()->length());
evacuation_info.increment_collectionset_used_after(cl.after_used_bytes());
G1Policy* policy = g1_policy();
policy->record_max_rs_lengths(cl.rs_lengths());
policy->cset_regions_freed();
double end_sec = os::elapsedTime();
double elapsed_ms = (end_sec - start_sec) * 1000.0;
prepend_to_freelist(cl.local_free_list());
decrement_summary_bytes(cl.before_used_bytes());
if (non_young) {
non_young_time_ms += elapsed_ms;
} else {
young_time_ms += elapsed_ms;
}
policy->add_bytes_allocated_in_old_since_last_gc(cl.bytes_allocated_in_old_since_last_gc());
prepend_to_freelist(&local_free_list);
decrement_summary_bytes(pre_used);
policy->phase_times()->record_young_free_cset_time_ms(young_time_ms);
policy->phase_times()->record_non_young_free_cset_time_ms(non_young_time_ms);
_old_evac_stats.add_failure_used_and_waste(cl.failure_used_words(), cl.failure_waste_words());
policy->phase_times()->record_young_free_cset_time_ms(cl.young_time() * 1000.0);
policy->phase_times()->record_non_young_free_cset_time_ms(cl.non_young_time() * 1000.0);
collection_set->clear();
}
class G1FreeHumongousRegionClosure : public HeapRegionClosure {
@ -4960,25 +4875,22 @@ void G1CollectedHeap::eagerly_reclaim_humongous_regions() {
cl.humongous_free_count());
}
// This routine is similar to the above but does not record
// any policy statistics or update free lists; we are abandoning
// the current incremental collection set in preparation of a
// full collection. After the full GC we will start to build up
// the incremental collection set again.
// This is only called when we're doing a full collection
// and is immediately followed by the tearing down of the young list.
void G1CollectedHeap::abandon_collection_set(HeapRegion* cs_head) {
HeapRegion* cur = cs_head;
while (cur != NULL) {
HeapRegion* next = cur->next_in_collection_set();
assert(cur->in_collection_set(), "bad CS");
cur->set_next_in_collection_set(NULL);
clear_in_cset(cur);
cur->set_young_index_in_cset(-1);
cur = next;
class G1AbandonCollectionSetClosure : public HeapRegionClosure {
public:
virtual bool doHeapRegion(HeapRegion* r) {
assert(r->in_collection_set(), "Region %u must have been in collection set", r->hrm_index());
G1CollectedHeap::heap()->clear_in_cset(r);
r->set_young_index_in_cset(-1);
return false;
}
};
void G1CollectedHeap::abandon_collection_set(G1CollectionSet* collection_set) {
G1AbandonCollectionSetClosure cl;
collection_set->iterate(&cl);
collection_set->clear();
collection_set->stop_incremental_building();
}
void G1CollectedHeap::set_free_regions_coming() {

View File

@ -778,13 +778,13 @@ protected:
// The closure used to refine a single card.
RefineCardTableEntryClosure* _refine_cte_cl;
// After a collection pause, make the regions in the CS into free
// After a collection pause, convert the regions in the collection set into free
// regions.
void free_collection_set(HeapRegion* cs_head, EvacuationInfo& evacuation_info, const size_t* surviving_young_words);
void free_collection_set(G1CollectionSet* collection_set, EvacuationInfo& evacuation_info, const size_t* surviving_young_words);
// Abandon the current collection set without recording policy
// statistics or updating free lists.
void abandon_collection_set(HeapRegion* cs_head);
void abandon_collection_set(G1CollectionSet* collection_set);
// The concurrent marker (and the thread it runs in.)
G1ConcurrentMark* _cm;
@ -930,16 +930,6 @@ protected:
// discovery.
G1CMIsAliveClosure _is_alive_closure_cm;
// Cache used by G1CollectedHeap::start_cset_region_for_worker().
HeapRegion** _worker_cset_start_region;
// Time stamp to validate the regions recorded in the cache
// used by G1CollectedHeap::start_cset_region_for_worker().
// The heap region entry for a given worker is valid iff
// the associated time stamp value matches the current value
// of G1CollectedHeap::_gc_time_stamp.
uint* _worker_cset_start_region_time_stamp;
volatile bool _free_regions_coming;
public:
@ -1211,19 +1201,14 @@ public:
HeapRegionClaimer* hrclaimer,
bool concurrent = false) const;
// Clear the cached cset start regions and (more importantly)
// the time stamps. Called when we reset the GC time stamp.
void clear_cset_start_regions();
// Given the id of a worker, obtain or calculate a suitable
// starting region for iterating over the current collection set.
HeapRegion* start_cset_region_for_worker(uint worker_i);
// Iterate over the regions (if any) in the current collection set.
void collection_set_iterate(HeapRegionClosure* blk);
// As above but starting from region r
void collection_set_iterate_from(HeapRegion* r, HeapRegionClosure *blk);
// Iterate over the regions (if any) in the current collection set. Starts the
// iteration over the entire collection set so that the start regions of a given
// worker id over the set active_workers are evenly spread across the set of
// collection set regions.
void collection_set_iterate_from(HeapRegionClosure *blk, uint worker_id);
HeapRegion* next_compaction_region(const HeapRegion* from) const;

View File

@ -89,16 +89,13 @@ inline HeapRegion* G1CollectedHeap::heap_region_containing(const T addr) const {
}
inline void G1CollectedHeap::reset_gc_time_stamp() {
assert_at_safepoint(true);
_gc_time_stamp = 0;
OrderAccess::fence();
// Clear the cached CSet starting regions and time stamps.
// Their validity is dependent on the GC timestamp.
clear_cset_start_regions();
}
inline void G1CollectedHeap::increment_gc_time_stamp() {
assert_at_safepoint(true);
++_gc_time_stamp;
OrderAccess::fence();
}
inline void G1CollectedHeap::old_set_add(HeapRegion* hr) {

View File

@ -30,6 +30,7 @@
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/g1/heapRegionRemSet.hpp"
#include "gc/g1/heapRegionSet.hpp"
#include "logging/logStream.hpp"
#include "utilities/debug.hpp"
G1CollectorState* G1CollectionSet::collector_state() {
@ -55,48 +56,63 @@ G1CollectionSet::G1CollectionSet(G1CollectedHeap* g1h, G1Policy* policy) :
_eden_region_length(0),
_survivor_region_length(0),
_old_region_length(0),
_head(NULL),
_bytes_used_before(0),
_recorded_rs_lengths(0),
_collection_set_regions(NULL),
_collection_set_cur_length(0),
_collection_set_max_length(0),
// Incremental CSet attributes
_inc_build_state(Inactive),
_inc_head(NULL),
_inc_tail(NULL),
_inc_bytes_used_before(0),
_inc_recorded_rs_lengths(0),
_inc_recorded_rs_lengths_diffs(0),
_inc_predicted_elapsed_time_ms(0.0),
_inc_predicted_elapsed_time_ms_diffs(0.0),
_inc_region_length(0) {}
_inc_predicted_elapsed_time_ms_diffs(0.0) {
}
G1CollectionSet::~G1CollectionSet() {
if (_collection_set_regions != NULL) {
FREE_C_HEAP_ARRAY(uint, _collection_set_regions);
}
delete _cset_chooser;
}
void G1CollectionSet::init_region_lengths(uint eden_cset_region_length,
uint survivor_cset_region_length) {
assert_at_safepoint(true);
_eden_region_length = eden_cset_region_length;
_survivor_region_length = survivor_cset_region_length;
assert(young_region_length() == _inc_region_length, "should match %u == %u", young_region_length(), _inc_region_length);
assert((size_t) young_region_length() == _collection_set_cur_length,
"Young region length %u should match collection set length " SIZE_FORMAT, young_region_length(), _collection_set_cur_length);
_old_region_length = 0;
}
void G1CollectionSet::initialize(uint max_region_length) {
guarantee(_collection_set_regions == NULL, "Must only initialize once.");
_collection_set_max_length = max_region_length;
_collection_set_regions = NEW_C_HEAP_ARRAY(uint, max_region_length, mtGC);
}
void G1CollectionSet::set_recorded_rs_lengths(size_t rs_lengths) {
_recorded_rs_lengths = rs_lengths;
}
// Add the heap region at the head of the non-incremental collection set
void G1CollectionSet::add_old_region(HeapRegion* hr) {
assert_at_safepoint(true);
assert(_inc_build_state == Active, "Precondition");
assert(hr->is_old(), "the region should be old");
assert(!hr->in_collection_set(), "should not already be in the CSet");
_g1->register_old_region_with_cset(hr);
hr->set_next_in_collection_set(_head);
_head = hr;
_collection_set_regions[_collection_set_cur_length++] = hr->hrm_index();
assert(_collection_set_cur_length <= _collection_set_max_length, "Collection set now larger than maximum size.");
_bytes_used_before += hr->used();
size_t rs_length = hr->rem_set()->occupied();
_recorded_rs_lengths += rs_length;
@ -105,12 +121,10 @@ void G1CollectionSet::add_old_region(HeapRegion* hr) {
// Initialize the per-collection-set information
void G1CollectionSet::start_incremental_building() {
assert(_collection_set_cur_length == 0, "Collection set must be empty before starting a new collection set.");
assert(_inc_build_state == Inactive, "Precondition");
_inc_head = NULL;
_inc_tail = NULL;
_inc_bytes_used_before = 0;
_inc_region_length = 0;
_inc_recorded_rs_lengths = 0;
_inc_recorded_rs_lengths_diffs = 0;
@ -151,6 +165,38 @@ void G1CollectionSet::finalize_incremental_building() {
_inc_predicted_elapsed_time_ms_diffs = 0.0;
}
void G1CollectionSet::clear() {
assert_at_safepoint(true);
_collection_set_cur_length = 0;
}
void G1CollectionSet::iterate(HeapRegionClosure* cl) const {
iterate_from(cl, 0, 1);
}
void G1CollectionSet::iterate_from(HeapRegionClosure* cl, uint worker_id, uint total_workers) const {
size_t len = _collection_set_cur_length;
OrderAccess::loadload();
if (len == 0) {
return;
}
size_t start_pos = (worker_id * len) / total_workers;
size_t cur_pos = start_pos;
do {
HeapRegion* r = G1CollectedHeap::heap()->region_at(_collection_set_regions[cur_pos]);
bool result = cl->doHeapRegion(r);
if (result) {
cl->incomplete();
return;
}
cur_pos++;
if (cur_pos == len) {
cur_pos = 0;
}
} while (cur_pos != start_pos);
}
void G1CollectionSet::update_young_region_prediction(HeapRegion* hr,
size_t new_rs_length) {
// Update the CSet information that is dependent on the new RS length
@ -183,8 +229,16 @@ void G1CollectionSet::add_young_region_common(HeapRegion* hr) {
assert(hr->is_young(), "invariant");
assert(_inc_build_state == Active, "Precondition");
hr->set_young_index_in_cset(_inc_region_length);
_inc_region_length++;
size_t collection_set_length = _collection_set_cur_length;
assert(collection_set_length <= INT_MAX, "Collection set is too large with %d entries", (int)collection_set_length);
hr->set_young_index_in_cset((int)collection_set_length);
_collection_set_regions[collection_set_length] = hr->hrm_index();
// Concurrent readers must observe the store of the value in the array before an
// update to the length field.
OrderAccess::storestore();
_collection_set_cur_length++;
assert(_collection_set_cur_length <= _collection_set_max_length, "Collection set larger than maximum allowed.");
// This routine is used when:
// * adding survivor regions to the incremental cset at the end of an
@ -218,59 +272,81 @@ void G1CollectionSet::add_young_region_common(HeapRegion* hr) {
assert(!hr->in_collection_set(), "invariant");
_g1->register_young_region_with_cset(hr);
assert(hr->next_in_collection_set() == NULL, "invariant");
}
// Add the region at the RHS of the incremental cset
void G1CollectionSet::add_survivor_regions(HeapRegion* hr) {
// We should only ever be appending survivors at the end of a pause
assert(hr->is_survivor(), "Logic");
// Do the 'common' stuff
assert(hr->is_survivor(), "Must only add survivor regions, but is %s", hr->get_type_str());
add_young_region_common(hr);
// Now add the region at the right hand side
if (_inc_tail == NULL) {
assert(_inc_head == NULL, "invariant");
_inc_head = hr;
} else {
_inc_tail->set_next_in_collection_set(hr);
}
_inc_tail = hr;
}
// Add the region to the LHS of the incremental cset
void G1CollectionSet::add_eden_region(HeapRegion* hr) {
// Survivors should be added to the RHS at the end of a pause
assert(hr->is_eden(), "Logic");
// Do the 'common' stuff
assert(hr->is_eden(), "Must only add eden regions, but is %s", hr->get_type_str());
add_young_region_common(hr);
// Add the region at the left hand side
hr->set_next_in_collection_set(_inc_head);
if (_inc_head == NULL) {
assert(_inc_tail == NULL, "Invariant");
_inc_tail = hr;
}
_inc_head = hr;
}
#ifndef PRODUCT
void G1CollectionSet::print(HeapRegion* list_head, outputStream* st) {
assert(list_head == inc_head() || list_head == head(), "must be");
class G1VerifyYoungAgesClosure : public HeapRegionClosure {
public:
bool _valid;
public:
G1VerifyYoungAgesClosure() : HeapRegionClosure(), _valid(true) { }
st->print_cr("\nCollection_set:");
HeapRegion* csr = list_head;
while (csr != NULL) {
HeapRegion* next = csr->next_in_collection_set();
assert(csr->in_collection_set(), "bad CS");
st->print_cr(" " HR_FORMAT ", P: " PTR_FORMAT "N: " PTR_FORMAT ", age: %4d",
HR_FORMAT_PARAMS(csr),
p2i(csr->prev_top_at_mark_start()), p2i(csr->next_top_at_mark_start()),
csr->age_in_surv_rate_group_cond());
csr = next;
virtual bool doHeapRegion(HeapRegion* r) {
guarantee(r->is_young(), "Region must be young but is %s", r->get_type_str());
SurvRateGroup* group = r->surv_rate_group();
if (group == NULL) {
log_error(gc, verify)("## encountered NULL surv_rate_group in young region");
_valid = false;
}
if (r->age_in_surv_rate_group() < 0) {
log_error(gc, verify)("## encountered negative age in young region");
_valid = false;
}
return false;
}
bool valid() const { return _valid; }
};
bool G1CollectionSet::verify_young_ages() {
assert_at_safepoint(true);
G1VerifyYoungAgesClosure cl;
iterate(&cl);
if (!cl.valid()) {
LogStreamHandle(Error, gc, verify) log;
print(&log);
}
return cl.valid();
}
class G1PrintCollectionSetClosure : public HeapRegionClosure {
outputStream* _st;
public:
G1PrintCollectionSetClosure(outputStream* st) : HeapRegionClosure(), _st(st) { }
virtual bool doHeapRegion(HeapRegion* r) {
assert(r->in_collection_set(), "Region %u should be in collection set", r->hrm_index());
_st->print_cr(" " HR_FORMAT ", P: " PTR_FORMAT "N: " PTR_FORMAT ", age: %4d",
HR_FORMAT_PARAMS(r),
p2i(r->prev_top_at_mark_start()),
p2i(r->next_top_at_mark_start()),
r->age_in_surv_rate_group_cond());
return false;
}
};
void G1CollectionSet::print(outputStream* st) {
st->print_cr("\nCollection_set:");
G1PrintCollectionSetClosure cl(st);
iterate(&cl);
}
#endif // !PRODUCT
@ -281,7 +357,6 @@ double G1CollectionSet::finalize_young_part(double target_pause_time_ms, G1Survi
guarantee(target_pause_time_ms > 0.0,
"target_pause_time_ms = %1.6lf should be positive", target_pause_time_ms);
guarantee(_head == NULL, "Precondition");
size_t pending_cards = _policy->pending_cards();
double base_time_ms = _policy->predict_base_elapsed_time_ms(pending_cards);
@ -305,7 +380,6 @@ double G1CollectionSet::finalize_young_part(double target_pause_time_ms, G1Survi
// Clear the fields that point to the survivor list - they are all young now.
survivors->convert_to_eden();
_head = _inc_head;
_bytes_used_before = _inc_bytes_used_before;
time_remaining_ms = MAX2(time_remaining_ms - _inc_predicted_elapsed_time_ms, 0.0);
@ -422,23 +496,41 @@ void G1CollectionSet::finalize_old_part(double time_remaining_ms) {
}
#ifdef ASSERT
class G1VerifyYoungCSetIndicesClosure : public HeapRegionClosure {
private:
size_t _young_length;
int* _heap_region_indices;
public:
G1VerifyYoungCSetIndicesClosure(size_t young_length) : HeapRegionClosure(), _young_length(young_length) {
_heap_region_indices = NEW_C_HEAP_ARRAY(int, young_length, mtGC);
for (size_t i = 0; i < young_length; i++) {
_heap_region_indices[i] = -1;
}
}
~G1VerifyYoungCSetIndicesClosure() {
FREE_C_HEAP_ARRAY(int, _heap_region_indices);
}
virtual bool doHeapRegion(HeapRegion* r) {
const int idx = r->young_index_in_cset();
assert(idx > -1, "Young index must be set for all regions in the incremental collection set but is not for region %u.", r->hrm_index());
assert((size_t)idx < _young_length, "Young cset index too large for region %u", r->hrm_index());
assert(_heap_region_indices[idx] == -1,
"Index %d used by multiple regions, first use by region %u, second by region %u",
idx, _heap_region_indices[idx], r->hrm_index());
_heap_region_indices[idx] = r->hrm_index();
return false;
}
};
void G1CollectionSet::verify_young_cset_indices() const {
ResourceMark rm;
uint* heap_region_indices = NEW_RESOURCE_ARRAY(uint, young_region_length());
for (uint i = 0; i < young_region_length(); ++i) {
heap_region_indices[i] = (uint)-1;
}
assert_at_safepoint(true);
for (HeapRegion* hr = _inc_head; hr != NULL; hr = hr->next_in_collection_set()) {
const int idx = hr->young_index_in_cset();
assert(idx > -1, "must be set for all inc cset regions");
assert((uint)idx < young_region_length(), "young cset index too large");
assert(heap_region_indices[idx] == (uint)-1,
"index %d used by multiple regions, first use by %u, second by %u",
idx, heap_region_indices[idx], hr->hrm_index());
heap_region_indices[idx] = hr->hrm_index();
}
G1VerifyYoungCSetIndicesClosure cl(_collection_set_cur_length);
iterate(&cl);
}
#endif

View File

@ -47,10 +47,15 @@ class G1CollectionSet VALUE_OBJ_CLASS_SPEC {
uint _survivor_region_length;
uint _old_region_length;
// The head of the list (via "next_in_collection_set()") representing the
// current collection set. Set from the incrementally built collection
// set at the start of the pause.
HeapRegion* _head;
// The actual collection set as a set of region indices.
// All entries in _collection_set_regions below _collection_set_cur_length are
// assumed to be valid entries.
// We assume that at any time there is at most only one writer and (one or more)
// concurrent readers. This means we are good with using storestore and loadload
// barriers on the writer and reader respectively only.
uint* _collection_set_regions;
volatile size_t _collection_set_cur_length;
size_t _collection_set_max_length;
// The number of bytes in the collection set before the pause. Set from
// the incrementally built collection set at the start of an evacuation
@ -71,12 +76,6 @@ class G1CollectionSet VALUE_OBJ_CLASS_SPEC {
CSetBuildType _inc_build_state;
// The head of the incrementally built collection set.
HeapRegion* _inc_head;
// The tail of the incrementally built collection set.
HeapRegion* _inc_tail;
// The number of bytes in the incrementally built collection set.
// Used to set _collection_set_bytes_used_before at the start of
// an evacuation pause.
@ -105,8 +104,6 @@ class G1CollectionSet VALUE_OBJ_CLASS_SPEC {
// See the comment for _inc_recorded_rs_lengths_diffs.
double _inc_predicted_elapsed_time_ms_diffs;
uint _inc_region_length;
G1CollectorState* collector_state();
G1GCPhaseTimes* phase_times();
@ -117,6 +114,9 @@ public:
G1CollectionSet(G1CollectedHeap* g1h, G1Policy* policy);
~G1CollectionSet();
// Initializes the collection set giving the maximum possible length of the collection set.
void initialize(uint max_region_length);
CollectionSetChooser* cset_chooser();
void init_region_lengths(uint eden_cset_region_length,
@ -133,36 +133,31 @@ public:
uint survivor_region_length() const { return _survivor_region_length; }
uint old_region_length() const { return _old_region_length; }
// Incremental CSet Support
// The head of the incrementally built collection set.
HeapRegion* inc_head() { return _inc_head; }
// The tail of the incrementally built collection set.
HeapRegion* inc_tail() { return _inc_tail; }
// Incremental collection set support
// Initialize incremental collection set info.
void start_incremental_building();
// Perform any final calculations on the incremental CSet fields
// Perform any final calculations on the incremental collection set fields
// before we can use them.
void finalize_incremental_building();
void clear_incremental() {
_inc_head = NULL;
_inc_tail = NULL;
_inc_region_length = 0;
}
// Reset the contents of the collection set.
void clear();
// Stop adding regions to the incremental collection set
// Iterate over the collection set, applying the given HeapRegionClosure on all of them.
// If may_be_aborted is true, iteration may be aborted using the return value of the
// called closure method.
void iterate(HeapRegionClosure* cl) const;
// Iterate over the collection set, applying the given HeapRegionClosure on all of them,
// trying to optimally spread out starting position of total_workers workers given the
// caller's worker_id.
void iterate_from(HeapRegionClosure* cl, uint worker_id, uint total_workers) const;
// Stop adding regions to the incremental collection set.
void stop_incremental_building() { _inc_build_state = Inactive; }
// The head of the list (via "next_in_collection_set()") representing the
// current collection set.
HeapRegion* head() { return _head; }
void clear_head() { _head = NULL; }
size_t recorded_rs_lengths() { return _recorded_rs_lengths; }
size_t bytes_used_before() const {
@ -174,33 +169,32 @@ public:
}
// Choose a new collection set. Marks the chosen regions as being
// "in_collection_set", and links them together. The head and number of
// the collection set are available via access methods.
// "in_collection_set".
double finalize_young_part(double target_pause_time_ms, G1SurvivorRegions* survivors);
void finalize_old_part(double time_remaining_ms);
// Add old region "hr" to the CSet.
// Add old region "hr" to the collection set.
void add_old_region(HeapRegion* hr);
// Update information about hr in the aggregated information for
// the incrementally built collection set.
void update_young_region_prediction(HeapRegion* hr, size_t new_rs_length);
// Add hr to the LHS of the incremental collection set.
// Add eden region to the collection set.
void add_eden_region(HeapRegion* hr);
// Add hr to the RHS of the incremental collection set.
// Add survivor region to the collection set.
void add_survivor_regions(HeapRegion* hr);
#ifndef PRODUCT
void print(HeapRegion* list_head, outputStream* st);
bool verify_young_ages();
void print(outputStream* st);
#endif // !PRODUCT
private:
// Update the incremental cset information when adding a region
// (should not be called directly).
// Update the incremental collection set information when adding a region.
void add_young_region_common(HeapRegion* hr);
};
#endif // SHARE_VM_GC_G1_G1COLLECTIONSET_HPP

View File

@ -394,37 +394,6 @@ void G1DefaultPolicy::update_rs_lengths_prediction(size_t prediction) {
}
}
#ifndef PRODUCT
bool G1DefaultPolicy::verify_young_ages() {
bool ret = true;
for (HeapRegion* curr = _collection_set->inc_head();
curr != NULL;
curr = curr->next_in_collection_set()) {
guarantee(curr->is_young(), "Region must be young");
SurvRateGroup* group = curr->surv_rate_group();
if (group == NULL) {
log_error(gc, verify)("## encountered NULL surv_rate_group in young region");
ret = false;
}
if (curr->age_in_surv_rate_group() < 0) {
log_error(gc, verify)("## encountered negative age in young region");
ret = false;
}
}
if (!ret) {
LogStreamHandle(Error, gc, verify) log;
_collection_set->print(_collection_set->inc_head(), &log);
}
return ret;
}
#endif // PRODUCT
void G1DefaultPolicy::record_full_collection_start() {
_full_collection_start_sec = os::elapsedTime();
// Release the future to-space so that it is available for compaction into.
@ -488,7 +457,7 @@ void G1DefaultPolicy::record_collection_pause_start(double start_time_sec) {
_short_lived_surv_rate_group->stop_adding_regions();
_survivors_age_table.clear();
assert( verify_young_ages(), "region age verification" );
assert(_g1->collection_set()->verify_young_ages(), "region age verification failed");
}
void G1DefaultPolicy::record_concurrent_mark_init_end(double mark_init_elapsed_time_ms) {

View File

@ -89,10 +89,6 @@ class G1DefaultPolicy: public G1Policy {
size_t _rs_lengths_prediction;
#ifndef PRODUCT
bool verify_young_ages(HeapRegion* head, SurvRateGroup *surv_rate_group);
#endif // PRODUCT
size_t _pending_cards;
// The amount of allocated bytes in old gen during the last mutator and the following
@ -116,10 +112,6 @@ public:
hr->install_surv_rate_group(_survivor_surv_rate_group);
}
#ifndef PRODUCT
bool verify_young_ages();
#endif // PRODUCT
void record_max_rs_lengths(size_t rs_lengths) {
_max_rs_lengths = rs_lengths;
}

View File

@ -251,6 +251,5 @@ G1ParRemoveSelfForwardPtrsTask::G1ParRemoveSelfForwardPtrsTask() :
void G1ParRemoveSelfForwardPtrsTask::work(uint worker_id) {
RemoveSelfForwardPtrHRClosure rsfp_cl(worker_id, &_hrclaimer);
HeapRegion* hr = _g1h->start_cset_region_for_worker(worker_id);
_g1h->collection_set_iterate_from(hr, &rsfp_cl);
_g1h->collection_set_iterate_from(&rsfp_cl, worker_id);
}

View File

@ -580,15 +580,20 @@ void G1HeapVerifier::verify_dirty_region(HeapRegion* hr) {
}
}
void G1HeapVerifier::verify_dirty_young_list(HeapRegion* head) {
G1SATBCardTableModRefBS* ct_bs = _g1h->g1_barrier_set();
for (HeapRegion* hr = head; hr != NULL; hr = hr->next_in_collection_set()) {
verify_dirty_region(hr);
class G1VerifyDirtyYoungListClosure : public HeapRegionClosure {
private:
G1HeapVerifier* _verifier;
public:
G1VerifyDirtyYoungListClosure(G1HeapVerifier* verifier) : HeapRegionClosure(), _verifier(verifier) { }
virtual bool doHeapRegion(HeapRegion* r) {
_verifier->verify_dirty_region(r);
return false;
}
}
};
void G1HeapVerifier::verify_dirty_young_regions() {
verify_dirty_young_list(_g1h->collection_set()->inc_head());
G1VerifyDirtyYoungListClosure cl(this);
_g1h->collection_set()->iterate(&cl);
}
bool G1HeapVerifier::verify_no_bits_over_tams(const char* bitmap_name, G1CMBitMapRO* bitmap,

View File

@ -108,7 +108,6 @@ public:
void verify_not_dirty_region(HeapRegion* hr) PRODUCT_RETURN;
void verify_dirty_region(HeapRegion* hr) PRODUCT_RETURN;
void verify_dirty_young_list(HeapRegion* head) PRODUCT_RETURN;
void verify_dirty_young_regions() PRODUCT_RETURN;
};

View File

@ -382,10 +382,8 @@ size_t G1RemSet::scan_rem_set(G1ParPushHeapRSClosure* oops_in_heap_closure,
uint worker_i) {
double rs_time_start = os::elapsedTime();
HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i);
G1ScanRSClosure cl(_scan_state, oops_in_heap_closure, heap_region_codeblobs, worker_i);
_g1->collection_set_iterate_from(startRegion, &cl);
_g1->collection_set_iterate_from(&cl, worker_i);
double scan_rs_time_sec = (os::elapsedTime() - rs_time_start) -
cl.strong_code_root_scan_time_sec();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2016, 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
@ -154,8 +154,8 @@ void G1StringDedupQueue::unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* c
}
void G1StringDedupQueue::print_statistics() {
log_debug(gc, stringdedup)(" [Queue]");
log_debug(gc, stringdedup)(" [Dropped: " UINTX_FORMAT "]", _queue->_dropped);
log_debug(gc, stringdedup)(" Queue");
log_debug(gc, stringdedup)(" Dropped: " UINTX_FORMAT, _queue->_dropped);
}
void G1StringDedupQueue::verify() {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2016, 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
@ -42,7 +42,9 @@ G1StringDedupStat::G1StringDedupStat() :
_idle(0),
_exec(0),
_block(0),
_start(0.0),
_start_concurrent(0.0),
_end_concurrent(0.0),
_start_phase(0.0),
_idle_elapsed(0.0),
_exec_elapsed(0.0),
_block_elapsed(0.0) {
@ -69,7 +71,13 @@ void G1StringDedupStat::add(const G1StringDedupStat& stat) {
_block_elapsed += stat._block_elapsed;
}
void G1StringDedupStat::print_summary(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat) {
void G1StringDedupStat::print_start(const G1StringDedupStat& last_stat) {
log_info(gc, stringdedup)(
"Concurrent String Deduplication (" G1_STRDEDUP_TIME_FORMAT ")",
G1_STRDEDUP_TIME_PARAM(last_stat._start_concurrent));
}
void G1StringDedupStat::print_end(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat) {
double total_deduped_bytes_percent = 0.0;
if (total_stat._new_bytes > 0) {
@ -79,13 +87,16 @@ void G1StringDedupStat::print_summary(const G1StringDedupStat& last_stat, const
log_info(gc, stringdedup)(
"Concurrent String Deduplication "
G1_STRDEDUP_BYTES_FORMAT_NS "->" G1_STRDEDUP_BYTES_FORMAT_NS "(" G1_STRDEDUP_BYTES_FORMAT_NS "), avg "
G1_STRDEDUP_PERCENT_FORMAT_NS ", " G1_STRDEDUP_TIME_FORMAT,
G1_STRDEDUP_BYTES_FORMAT_NS "->" G1_STRDEDUP_BYTES_FORMAT_NS "(" G1_STRDEDUP_BYTES_FORMAT_NS ") "
"avg " G1_STRDEDUP_PERCENT_FORMAT_NS " "
"(" G1_STRDEDUP_TIME_FORMAT ", " G1_STRDEDUP_TIME_FORMAT ") " G1_STRDEDUP_TIME_FORMAT_MS,
G1_STRDEDUP_BYTES_PARAM(last_stat._new_bytes),
G1_STRDEDUP_BYTES_PARAM(last_stat._new_bytes - last_stat._deduped_bytes),
G1_STRDEDUP_BYTES_PARAM(last_stat._deduped_bytes),
total_deduped_bytes_percent,
last_stat._exec_elapsed);
G1_STRDEDUP_TIME_PARAM(last_stat._start_concurrent),
G1_STRDEDUP_TIME_PARAM(last_stat._end_concurrent),
G1_STRDEDUP_TIME_PARAM_MS(last_stat._exec_elapsed));
}
void G1StringDedupStat::print_statistics(const G1StringDedupStat& stat, bool total) {
@ -134,23 +145,31 @@ void G1StringDedupStat::print_statistics(const G1StringDedupStat& stat, bool tot
if (total) {
log_debug(gc, stringdedup)(
" [Total Exec: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT ", Idle: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT ", Blocked: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT "]",
stat._exec, stat._exec_elapsed, stat._idle, stat._idle_elapsed, stat._block, stat._block_elapsed);
" Total Exec: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT_MS
", Idle: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT_MS
", Blocked: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT_MS,
stat._exec, G1_STRDEDUP_TIME_PARAM_MS(stat._exec_elapsed),
stat._idle, G1_STRDEDUP_TIME_PARAM_MS(stat._idle_elapsed),
stat._block, G1_STRDEDUP_TIME_PARAM_MS(stat._block_elapsed));
} else {
log_debug(gc, stringdedup)(
" [Last Exec: " G1_STRDEDUP_TIME_FORMAT ", Idle: " G1_STRDEDUP_TIME_FORMAT ", Blocked: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT "]",
stat._exec_elapsed, stat._idle_elapsed, stat._block, stat._block_elapsed);
" Last Exec: " G1_STRDEDUP_TIME_FORMAT_MS
", Idle: " G1_STRDEDUP_TIME_FORMAT_MS
", Blocked: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT_MS,
G1_STRDEDUP_TIME_PARAM_MS(stat._exec_elapsed),
G1_STRDEDUP_TIME_PARAM_MS(stat._idle_elapsed),
stat._block, G1_STRDEDUP_TIME_PARAM_MS(stat._block_elapsed));
}
log_debug(gc, stringdedup)(" [Inspected: " G1_STRDEDUP_OBJECTS_FORMAT "]", stat._inspected);
log_debug(gc, stringdedup)(" [Skipped: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]", stat._skipped, skipped_percent);
log_debug(gc, stringdedup)(" [Hashed: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]", stat._hashed, hashed_percent);
log_debug(gc, stringdedup)(" [Known: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]", stat._known, known_percent);
log_debug(gc, stringdedup)(" [New: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "]",
log_debug(gc, stringdedup)(" Inspected: " G1_STRDEDUP_OBJECTS_FORMAT, stat._inspected);
log_debug(gc, stringdedup)(" Skipped: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")", stat._skipped, skipped_percent);
log_debug(gc, stringdedup)(" Hashed: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")", stat._hashed, hashed_percent);
log_debug(gc, stringdedup)(" Known: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")", stat._known, known_percent);
log_debug(gc, stringdedup)(" New: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT,
stat._new, new_percent, G1_STRDEDUP_BYTES_PARAM(stat._new_bytes));
log_debug(gc, stringdedup)(" [Deduplicated: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]",
log_debug(gc, stringdedup)(" Deduplicated: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")",
stat._deduped, deduped_percent, G1_STRDEDUP_BYTES_PARAM(stat._deduped_bytes), deduped_bytes_percent);
log_debug(gc, stringdedup)(" [Young: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]",
log_debug(gc, stringdedup)(" Young: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")",
stat._deduped_young, deduped_young_percent, G1_STRDEDUP_BYTES_PARAM(stat._deduped_young_bytes), deduped_young_bytes_percent);
log_debug(gc, stringdedup)(" [Old: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]",
log_debug(gc, stringdedup)(" Old: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")",
stat._deduped_old, deduped_old_percent, G1_STRDEDUP_BYTES_PARAM(stat._deduped_old_bytes), deduped_old_bytes_percent);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2016, 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
@ -30,11 +30,14 @@
// Macros for GC log output formating
#define G1_STRDEDUP_OBJECTS_FORMAT UINTX_FORMAT_W(12)
#define G1_STRDEDUP_TIME_FORMAT "%1.7lf secs"
#define G1_STRDEDUP_PERCENT_FORMAT "%5.1lf%%"
#define G1_STRDEDUP_PERCENT_FORMAT_NS "%.1lf%%"
#define G1_STRDEDUP_BYTES_FORMAT "%8.1lf%s"
#define G1_STRDEDUP_BYTES_FORMAT_NS "%.1lf%s"
#define G1_STRDEDUP_TIME_FORMAT "%.3fs"
#define G1_STRDEDUP_TIME_PARAM(time) (time)
#define G1_STRDEDUP_TIME_FORMAT_MS "%.3fms"
#define G1_STRDEDUP_TIME_PARAM_MS(time) ((time) * MILLIUNITS)
#define G1_STRDEDUP_PERCENT_FORMAT "%5.1f%%"
#define G1_STRDEDUP_PERCENT_FORMAT_NS "%.1f%%"
#define G1_STRDEDUP_BYTES_FORMAT "%8.1f%s"
#define G1_STRDEDUP_BYTES_FORMAT_NS "%.1f%s"
#define G1_STRDEDUP_BYTES_PARAM(bytes) byte_size_in_proper_unit((double)(bytes)), proper_unit_for_byte_size((bytes))
//
@ -60,7 +63,9 @@ private:
uintx _block;
// Time spent by the deduplication thread in different phases
double _start;
double _start_concurrent;
double _end_concurrent;
double _start_phase;
double _idle_elapsed;
double _exec_elapsed;
double _block_elapsed;
@ -104,38 +109,41 @@ public:
}
void mark_idle() {
_start = os::elapsedTime();
_start_phase = os::elapsedTime();
_idle++;
}
void mark_exec() {
double now = os::elapsedTime();
_idle_elapsed = now - _start;
_start = now;
_idle_elapsed = now - _start_phase;
_start_phase = now;
_start_concurrent = now;
_exec++;
}
void mark_block() {
double now = os::elapsedTime();
_exec_elapsed += now - _start;
_start = now;
_exec_elapsed += now - _start_phase;
_start_phase = now;
_block++;
}
void mark_unblock() {
double now = os::elapsedTime();
_block_elapsed += now - _start;
_start = now;
_block_elapsed += now - _start_phase;
_start_phase = now;
}
void mark_done() {
double now = os::elapsedTime();
_exec_elapsed += now - _start;
_exec_elapsed += now - _start_phase;
_end_concurrent = now;
}
void add(const G1StringDedupStat& stat);
static void print_summary(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat);
static void print_start(const G1StringDedupStat& last_stat);
static void print_end(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat);
static void print_statistics(const G1StringDedupStat& stat, bool total);
};

View File

@ -196,7 +196,8 @@ void G1StringDedupEntryCache::delete_overflowed() {
}
double end = os::elapsedTime();
log_trace(gc, stringdedup)("Deleted " UINTX_FORMAT " entries, " G1_STRDEDUP_TIME_FORMAT, count, end - start);
log_trace(gc, stringdedup)("Deleted " UINTX_FORMAT " entries, " G1_STRDEDUP_TIME_FORMAT_MS,
count, G1_STRDEDUP_TIME_PARAM_MS(end - start));
}
G1StringDedupTable* G1StringDedupTable::_table = NULL;
@ -610,14 +611,14 @@ void G1StringDedupTable::clean_entry_cache() {
void G1StringDedupTable::print_statistics() {
Log(gc, stringdedup) log;
log.debug(" [Table]");
log.debug(" [Memory Usage: " G1_STRDEDUP_BYTES_FORMAT_NS "]",
log.debug(" Table");
log.debug(" Memory Usage: " G1_STRDEDUP_BYTES_FORMAT_NS,
G1_STRDEDUP_BYTES_PARAM(_table->_size * sizeof(G1StringDedupEntry*) + (_table->_entries + _entry_cache->size()) * sizeof(G1StringDedupEntry)));
log.debug(" [Size: " SIZE_FORMAT ", Min: " SIZE_FORMAT ", Max: " SIZE_FORMAT "]", _table->_size, _min_size, _max_size);
log.debug(" [Entries: " UINTX_FORMAT ", Load: " G1_STRDEDUP_PERCENT_FORMAT_NS ", Cached: " UINTX_FORMAT ", Added: " UINTX_FORMAT ", Removed: " UINTX_FORMAT "]",
log.debug(" Size: " SIZE_FORMAT ", Min: " SIZE_FORMAT ", Max: " SIZE_FORMAT, _table->_size, _min_size, _max_size);
log.debug(" Entries: " UINTX_FORMAT ", Load: " G1_STRDEDUP_PERCENT_FORMAT_NS ", Cached: " UINTX_FORMAT ", Added: " UINTX_FORMAT ", Removed: " UINTX_FORMAT,
_table->_entries, (double)_table->_entries / (double)_table->_size * 100.0, _entry_cache->size(), _entries_added, _entries_removed);
log.debug(" [Resize Count: " UINTX_FORMAT ", Shrink Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS "), Grow Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS ")]",
log.debug(" Resize Count: " UINTX_FORMAT ", Shrink Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS "), Grow Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS ")",
_resize_count, _table->_shrink_threshold, _shrink_load_factor * 100.0, _table->_grow_threshold, _grow_load_factor * 100.0);
log.debug(" [Rehash Count: " UINTX_FORMAT ", Rehash Threshold: " UINTX_FORMAT ", Hash Seed: 0x%x]", _rehash_count, _rehash_threshold, _table->_hash_seed);
log.debug(" [Age Threshold: " UINTX_FORMAT "]", StringDeduplicationAgeThreshold);
log.debug(" Rehash Count: " UINTX_FORMAT ", Rehash Threshold: " UINTX_FORMAT ", Hash Seed: 0x%x", _rehash_count, _rehash_threshold, _table->_hash_seed);
log.debug(" Age Threshold: " UINTX_FORMAT, StringDeduplicationAgeThreshold);
}

View File

@ -103,6 +103,7 @@ void G1StringDedupThread::run_service() {
SuspendibleThreadSetJoiner sts_join;
stat.mark_exec();
print_start(stat);
// Process the queue
for (;;) {
@ -123,9 +124,8 @@ void G1StringDedupThread::run_service() {
stat.mark_done();
// Print statistics
total_stat.add(stat);
print(stat, total_stat);
print_end(stat, total_stat);
}
G1StringDedupTable::clean_entry_cache();
@ -136,14 +136,16 @@ void G1StringDedupThread::stop_service() {
G1StringDedupQueue::cancel_wait();
}
void G1StringDedupThread::print(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat) {
if (log_is_enabled(Info, gc, stringdedup)) {
G1StringDedupStat::print_summary(last_stat, total_stat);
if (log_is_enabled(Debug, gc, stringdedup)) {
G1StringDedupStat::print_statistics(last_stat, false);
G1StringDedupStat::print_statistics(total_stat, true);
G1StringDedupTable::print_statistics();
G1StringDedupQueue::print_statistics();
}
void G1StringDedupThread::print_start(const G1StringDedupStat& last_stat) {
G1StringDedupStat::print_start(last_stat);
}
void G1StringDedupThread::print_end(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat) {
G1StringDedupStat::print_end(last_stat, total_stat);
if (log_is_enabled(Debug, gc, stringdedup)) {
G1StringDedupStat::print_statistics(last_stat, false);
G1StringDedupStat::print_statistics(total_stat, true);
G1StringDedupTable::print_statistics();
G1StringDedupQueue::print_statistics();
}
}

View File

@ -43,7 +43,8 @@ private:
G1StringDedupThread();
~G1StringDedupThread();
void print(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat);
void print_start(const G1StringDedupStat& last_stat);
void print_end(const G1StringDedupStat& last_stat, const G1StringDedupStat& total_stat);
void run_service();
void stop_service();

View File

@ -71,38 +71,51 @@ void G1YoungRemSetSamplingThread::stop_service() {
_monitor.notify();
}
class G1YoungRemSetSamplingClosure : public HeapRegionClosure {
SuspendibleThreadSetJoiner* _sts;
size_t _regions_visited;
size_t _sampled_rs_lengths;
public:
G1YoungRemSetSamplingClosure(SuspendibleThreadSetJoiner* sts) :
HeapRegionClosure(), _sts(sts), _regions_visited(0), _sampled_rs_lengths(0) { }
virtual bool doHeapRegion(HeapRegion* r) {
size_t rs_length = r->rem_set()->occupied();
_sampled_rs_lengths += rs_length;
// Update the collection set policy information for this region
G1CollectedHeap::heap()->collection_set()->update_young_region_prediction(r, rs_length);
_regions_visited++;
if (_regions_visited == 10) {
if (_sts->should_yield()) {
_sts->yield();
// A gc may have occurred and our sampling data is stale and further
// traversal of the collection set is unsafe
return true;
}
_regions_visited = 0;
}
return false;
}
size_t sampled_rs_lengths() const { return _sampled_rs_lengths; }
};
void G1YoungRemSetSamplingThread::sample_young_list_rs_lengths() {
SuspendibleThreadSetJoiner sts;
G1CollectedHeap* g1h = G1CollectedHeap::heap();
G1Policy* g1p = g1h->g1_policy();
G1CollectionSet* g1cs = g1h->collection_set();
if (g1p->adaptive_young_list_length()) {
int regions_visited = 0;
HeapRegion* hr = g1cs->inc_head();
size_t sampled_rs_lengths = 0;
G1YoungRemSetSamplingClosure cl(&sts);
while (hr != NULL) {
size_t rs_length = hr->rem_set()->occupied();
sampled_rs_lengths += rs_length;
G1CollectionSet* g1cs = g1h->collection_set();
g1cs->iterate(&cl);
// Update the collection set policy information for this region
g1cs->update_young_region_prediction(hr, rs_length);
++regions_visited;
// we try to yield every time we visit 10 regions
if (regions_visited == 10) {
if (sts.should_yield()) {
sts.yield();
// A gc may have occurred and our sampling data is stale and further
// traversal of the collection set is unsafe
return;
}
regions_visited = 0;
}
assert(hr == g1cs->inc_tail() || hr->next_in_collection_set() != NULL, "next should only be null at tail of icset");
hr = hr->next_in_collection_set();
if (cl.complete()) {
g1p->revise_young_list_target_length_if_necessary(cl.sampled_rs_lengths());
}
g1p->revise_young_list_target_length_if_necessary(sampled_rs_lengths);
}
}

View File

@ -284,7 +284,6 @@ HeapRegion::HeapRegion(uint hrm_index,
_hrm_index(hrm_index),
_allocation_context(AllocationContext::system()),
_humongous_start_region(NULL),
_next_in_special_set(NULL),
_evacuation_failed(false),
_prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0),
_next(NULL), _prev(NULL),

View File

@ -261,12 +261,6 @@ class HeapRegion: public G1ContiguousSpace {
// True iff an attempt to evacuate an object in the region failed.
bool _evacuation_failed;
// A heap region may be a member one of a number of special subsets, each
// represented as linked lists through the field below. Currently, there
// is only one set:
// The collection set.
HeapRegion* _next_in_special_set;
// Fields used by the HeapRegionSetBase class and subclasses.
HeapRegion* _next;
HeapRegion* _prev;
@ -476,9 +470,6 @@ class HeapRegion: public G1ContiguousSpace {
inline bool in_collection_set() const;
inline HeapRegion* next_in_collection_set() const;
inline void set_next_in_collection_set(HeapRegion* r);
void set_allocation_context(AllocationContext_t context) {
_allocation_context = context;
}
@ -744,7 +735,7 @@ class HeapRegion: public G1ContiguousSpace {
// Terminates the iteration when the "doHeapRegion" method returns "true".
class HeapRegionClosure : public StackObj {
friend class HeapRegionManager;
friend class G1CollectedHeap;
friend class G1CollectionSet;
bool _complete;
void incomplete() { _complete = false; }

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2016, 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
@ -230,18 +230,4 @@ inline bool HeapRegion::in_collection_set() const {
return G1CollectedHeap::heap()->is_in_cset(this);
}
inline HeapRegion* HeapRegion::next_in_collection_set() const {
assert(in_collection_set(), "should only invoke on member of CS.");
assert(_next_in_special_set == NULL ||
_next_in_special_set->in_collection_set(),
"Malformed CS.");
return _next_in_special_set;
}
void HeapRegion::set_next_in_collection_set(HeapRegion* r) {
assert(in_collection_set(), "should only invoke on member of CS.");
assert(r == NULL || r->in_collection_set(), "Malformed CS.");
_next_in_special_set = r;
}
#endif // SHARE_VM_GC_G1_HEAPREGION_INLINE_HPP

View File

@ -386,13 +386,21 @@ GCTaskThread* GCTaskManager::install_worker(uint t) {
void GCTaskManager::add_workers(bool initializing) {
os::ThreadType worker_type = os::pgc_thread;
uint previous_created_workers = _created_workers;
_created_workers = WorkerManager::add_workers(this,
_active_workers,
(uint) _workers,
_workers,
_created_workers,
worker_type,
initializing);
_active_workers = MIN2(_created_workers, _active_workers);
WorkerManager::log_worker_creation(this, previous_created_workers, _active_workers, _created_workers, initializing);
}
const char* GCTaskManager::group_name() {
return "ParGC Thread";
}
void GCTaskManager::initialize() {

View File

@ -556,6 +556,8 @@ protected:
GCTaskThread* install_worker(uint worker_id);
// Add GC workers as needed.
void add_workers(bool initializing);
// Base name (without worker id #) of threads.
const char* group_name();
};
//

View File

@ -45,7 +45,7 @@ GCTaskThread::GCTaskThread(GCTaskManager* manager,
_time_stamp_index(0)
{
set_id(which);
set_name("ParGC Thread#%d", which);
set_name("%s#%d", manager->group_name(), which);
}
GCTaskThread::~GCTaskThread() {

View File

@ -55,6 +55,7 @@ private:
return new GCTaskThread(manager, which, processor_id);
}
public:
static void destroy(GCTaskThread* manager) {
if (manager != NULL) {
delete manager;

View File

@ -159,6 +159,8 @@ class CollectedHeap : public CHeapObj<mtInternal> {
inline static void post_allocation_setup_array(KlassHandle klass,
HeapWord* obj, int length);
inline static void post_allocation_setup_class(KlassHandle klass, HeapWord* obj, int size);
// Clears an allocated object.
inline static void init_obj(HeapWord* obj, size_t size);
@ -300,6 +302,7 @@ class CollectedHeap : public CHeapObj<mtInternal> {
inline static oop obj_allocate(KlassHandle klass, int size, TRAPS);
inline static oop array_allocate(KlassHandle klass, int size, int length, TRAPS);
inline static oop array_allocate_nozero(KlassHandle klass, int size, int length, TRAPS);
inline static oop class_allocate(KlassHandle klass, int size, TRAPS);
inline static void post_allocation_install_obj_klass(KlassHandle klass,
oop obj);

View File

@ -25,6 +25,7 @@
#ifndef SHARE_VM_GC_SHARED_COLLECTEDHEAP_INLINE_HPP
#define SHARE_VM_GC_SHARED_COLLECTEDHEAP_INLINE_HPP
#include "classfile/javaClasses.hpp"
#include "gc/shared/allocTracer.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "gc/shared/threadLocalAllocBuffer.inline.hpp"
@ -96,6 +97,22 @@ void CollectedHeap::post_allocation_setup_obj(KlassHandle klass,
post_allocation_notify(klass, (oop)obj, size);
}
void CollectedHeap::post_allocation_setup_class(KlassHandle klass,
HeapWord* obj,
int size) {
// Set oop_size field before setting the _klass field
// in post_allocation_setup_common() because the klass field
// indicates that the object is parsable by concurrent GC.
oop new_cls = (oop)obj;
assert(size > 0, "oop_size must be positive.");
java_lang_Class::set_oop_size(new_cls, size);
post_allocation_setup_common(klass, obj);
assert(Universe::is_bootstrapping() ||
!new_cls->is_array(), "must not be an array");
// notify jvmti and dtrace
post_allocation_notify(klass, new_cls, size);
}
void CollectedHeap::post_allocation_setup_array(KlassHandle klass,
HeapWord* obj,
int length) {
@ -207,6 +224,16 @@ oop CollectedHeap::obj_allocate(KlassHandle klass, int size, TRAPS) {
return (oop)obj;
}
oop CollectedHeap::class_allocate(KlassHandle klass, int size, TRAPS) {
debug_only(check_for_valid_allocation_state());
assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed");
assert(size >= 0, "int won't convert to size_t");
HeapWord* obj = common_mem_allocate_init(klass, size, CHECK_NULL);
post_allocation_setup_class(klass, obj, size); // set oop_size
NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));
return (oop)obj;
}
oop CollectedHeap::array_allocate(KlassHandle klass,
int size,
int length,

View File

@ -47,18 +47,18 @@ class WorkerManager : public AllStatic {
// threads and a failure would not be optimal but should not be fatal.
template <class WorkerType>
static uint add_workers (WorkerType* holder,
uint active_workers,
uint total_workers,
uint created_workers,
os::ThreadType worker_type,
bool initializing) {
uint active_workers,
uint total_workers,
uint created_workers,
os::ThreadType worker_type,
bool initializing) {
uint start = created_workers;
uint end = MIN2(active_workers, total_workers);
for (uint worker_id = start; worker_id < end; worker_id += 1) {
WorkerThread* new_worker = holder->install_worker(worker_id);
assert(new_worker != NULL, "Failed to allocate GangWorker");
if (new_worker == NULL || !os::create_thread(new_worker, worker_type)) {
if(initializing) {
if (initializing) {
vm_exit_out_of_memory(0, OOM_MALLOC_ERROR,
"Cannot create worker GC thread. Out of system resources.");
}
@ -67,11 +67,21 @@ class WorkerManager : public AllStatic {
os::start_thread(new_worker);
}
log_trace(gc, task)("AdaptiveSizePolicy::add_workers() : "
"active_workers: %u created_workers: %u",
active_workers, created_workers);
return created_workers;
}
// Log (at trace level) a change in the number of created workers.
template <class WorkerType>
static void log_worker_creation(WorkerType* holder,
uint previous_created_workers,
uint active_workers,
uint created_workers,
bool initializing) {
if (previous_created_workers < created_workers) {
const char* initializing_msg = initializing ? "Adding initial" : "Creating additional";
log_trace(gc, task)("%s %s(s) previously created workers %u active workers %u total created workers %u",
initializing_msg, holder->group_name(), previous_created_workers, active_workers, created_workers);
}
}
};
#endif // SHARE_VM_GC_SHARED_WORKERMANAGER_HPP

View File

@ -66,6 +66,7 @@ void AbstractWorkGang::add_workers(uint active_workers, bool initializing) {
} else {
worker_type = os::pgc_thread;
}
uint previous_created_workers = _created_workers;
_created_workers = WorkerManager::add_workers(this,
active_workers,
@ -74,6 +75,8 @@ void AbstractWorkGang::add_workers(uint active_workers, bool initializing) {
worker_type,
initializing);
_active_workers = MIN2(_created_workers, _active_workers);
WorkerManager::log_worker_creation(this, previous_created_workers, _active_workers, _created_workers, initializing);
}
AbstractGangWorker* AbstractWorkGang::worker(uint i) const {

View File

@ -176,6 +176,9 @@ class AbstractWorkGang : public CHeapObj<mtInternal> {
// Return the Ith worker.
AbstractGangWorker* worker(uint i) const;
// Base name (without worker id #) of threads.
const char* group_name() { return name(); }
void threads_do(ThreadClosure* tc) const;
// Create a GC worker and install it into the work gang.

View File

@ -576,27 +576,27 @@ void InterpreterRuntime::resolve_get_put(JavaThread* thread, Bytecodes::Code byt
// compute auxiliary field attributes
TosState state = as_TosState(info.field_type());
// We need to delay resolving put instructions on final fields
// until we actually invoke one. This is required so we throw
// exceptions at the correct place. If we do not resolve completely
// in the current pass, leaving the put_code set to zero will
// cause the next put instruction to reresolve.
Bytecodes::Code put_code = (Bytecodes::Code)0;
// We also need to delay resolving getstatic instructions until the
// class is intitialized. This is required so that access to the static
// Put instructions on final fields are not resolved. This is required so we throw
// exceptions at the correct place (when the instruction is actually invoked).
// If we do not resolve an instruction in the current pass, leaving the put_code
// set to zero will cause the next put instruction to the same field to reresolve.
//
// Also, we need to delay resolving getstatic and putstatic instructions until the
// class is initialized. This is required so that access to the static
// field will call the initialization function every time until the class
// is completely initialized ala. in 2.17.5 in JVM Specification.
InstanceKlass* klass = InstanceKlass::cast(info.field_holder());
bool uninitialized_static = ((bytecode == Bytecodes::_getstatic || bytecode == Bytecodes::_putstatic) &&
!klass->is_initialized());
Bytecodes::Code get_code = (Bytecodes::Code)0;
Bytecodes::Code put_code = (Bytecodes::Code)0;
if (is_put && !info.access_flags().is_final() && !uninitialized_static) {
put_code = ((is_static) ? Bytecodes::_putstatic : Bytecodes::_putfield);
}
Bytecodes::Code get_code = (Bytecodes::Code)0;
if (!uninitialized_static) {
get_code = ((is_static) ? Bytecodes::_getstatic : Bytecodes::_getfield);
if (is_put || !info.access_flags().is_final()) {
put_code = ((is_static) ? Bytecodes::_putstatic : Bytecodes::_putfield);
}
}
cp_cache_entry->set_field(

View File

@ -970,7 +970,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd,
if (is_initialized_static_final_update || is_initialized_instance_final_update) {
ss.print("Update to %s final field %s.%s attempted from a different method (%s) than the initializer method %s ",
is_static ? "static" : "non-static", resolved_klass()->external_name(), fd.name()->as_C_string(),
current_klass()->external_name(),
m()->name()->as_C_string(),
is_static ? "<clinit>" : "<init>");
THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string());
}

View File

@ -415,17 +415,8 @@ void LogConfiguration::describe_available(outputStream* out){
void LogConfiguration::describe_current_configuration(outputStream* out){
out->print_cr("Log output configuration:");
for (size_t i = 0; i < _n_outputs; i++) {
out->print("#" SIZE_FORMAT ": %s ", i, _outputs[i]->name());
out->print_raw(_outputs[i]->config_string());
out->print(" ");
char delimiter[2] = {0};
for (size_t d = 0; d < LogDecorators::Count; d++) {
LogDecorators::Decorator decorator = static_cast<LogDecorators::Decorator>(d);
if (_outputs[i]->decorators().is_decorator(decorator)) {
out->print("%s%s", delimiter, LogDecorators::name(decorator));
*delimiter = ',';
}
}
out->print("#" SIZE_FORMAT ": ", i);
_outputs[i]->describe(out);
out->cr();
}
}

View File

@ -428,3 +428,13 @@ char* LogFileOutput::make_file_name(const char* file_name,
result[result_len] = '\0';
return result;
}
void LogFileOutput::describe(outputStream *out) {
LogOutput::describe(out);
out->print(" ");
out->print("filecount=%u,filesize=" SIZE_FORMAT "%s", _file_count,
byte_size_in_proper_unit(_rotate_size),
proper_unit_for_byte_size(_rotate_size));
}

View File

@ -85,6 +85,7 @@ class LogFileOutput : public LogFileStreamOutput {
virtual int write(const LogDecorations& decorations, const char* msg);
virtual int write(LogMessageBuffer::Iterator msg_iterator);
virtual void force_rotate();
virtual void describe(outputStream *out);
virtual const char* name() const {
return _name;

View File

@ -83,3 +83,18 @@ void LogOutput::add_to_config_string(const LogTagSet* ts, LogLevelType level) {
break;
}
}
void LogOutput::describe(outputStream *out) {
out->print("%s ", name());
out->print_raw(config_string());
out->print(" ");
char delimiter[2] = {0};
for (size_t d = 0; d < LogDecorators::Count; d++) {
LogDecorators::Decorator decorator = static_cast<LogDecorators::Decorator>(d);
if (decorators().is_decorator(decorator)) {
out->print("%s%s", delimiter, LogDecorators::name(decorator));
*delimiter = ',';
}
}
}

View File

@ -83,6 +83,8 @@ class LogOutput : public CHeapObj<mtLogging> {
// Do nothing by default.
}
virtual void describe(outputStream *out);
virtual const char* name() const = 0;
virtual bool initialize(const char* options, outputStream* errstream) = 0;
virtual int write(const LogDecorations& decorations, const char* msg) = 0;

View File

@ -74,6 +74,7 @@ DEBUG_ONLY(size_t Test_log_prefix_prefixer(char* buf, size_t len);)
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ref)) \
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ref, start)) \
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, start)) \
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, stringtable)) \
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, sweep)) \
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, task)) \
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, task, start)) \

View File

@ -3106,10 +3106,6 @@ void Metaspace::ergo_initialize() {
assert(MetaspaceSize <= MaxMetaspaceSize, "MetaspaceSize should be limited by MaxMetaspaceSize");
if (MetaspaceSize < 256*K) {
vm_exit_during_initialization("Too small initial Metaspace size");
}
MinMetaspaceExpansion = align_size_down_bounded(MinMetaspaceExpansion, _commit_alignment);
MaxMetaspaceExpansion = align_size_down_bounded(MaxMetaspaceExpansion, _commit_alignment);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016, 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
@ -50,13 +50,12 @@ instanceOop InstanceMirrorKlass::allocate_instance(KlassHandle k, TRAPS) {
// Query before forming handle.
int size = instance_size(k);
KlassHandle h_k(THREAD, this);
instanceOop i = (instanceOop)CollectedHeap::obj_allocate(h_k, size, CHECK_NULL);
assert(size > 0, "total object size must be positive: %d", size);
// Since mirrors can be variable sized because of the static fields, store
// the size in the mirror itself.
java_lang_Class::set_oop_size(i, size);
return i;
return (instanceOop)CollectedHeap::class_allocate(h_k, size, CHECK_NULL);
}
int InstanceMirrorKlass::oop_size(oop obj) const {

View File

@ -258,8 +258,8 @@ int oopDesc::size_given_klass(Klass* klass) {
}
}
assert(s % MinObjAlignment == 0, "alignment check");
assert(s > 0, "Bad size calculated");
assert(s % MinObjAlignment == 0, "Oop size is not properly aligned: %d", s);
assert(s > 0, "Oop size must be greater than zero, not %d", s);
return s;
}

View File

@ -6509,6 +6509,59 @@ class C2 extends C1 implements I2 {
<errors>
</errors>
</function>
<function id="GetNamedModule" num="40" since="9">
<synopsis>Get Named Module</synopsis>
<description>
Return the <code>java.lang.reflect.Module</code> object for a named
module defined to a class loader that contains a given package.
The module is returned via <code>module_ptr</code>.
<p/>
If a named module is defined to the class loader and it
contains the package then that named module is returned,
otherwise <code>NULL</code> is returned.
<p/>
</description>
<origin>new</origin>
<capabilities>
</capabilities>
<parameters>
<param id="class_loader">
<ptrtype>
<jobject/>
<nullok>the bootstrap loader is assumed</nullok>
</ptrtype>
<description>
A class loader.
If the <code>class_loader</code> is not <code>NULL</code>
or a subclass of <code>java.lang.ClassLoader</code>
this function returns
<errorlink id="JVMTI_ERROR_ILLEGAL_ARGUMENT"></errorlink>.
</description>
</param>
<param id="package_name">
<inbuf><char/></inbuf>
<description>
The name of the package, encoded as a
<internallink id="mUTF">modified UTF-8</internallink> string.
The package name is in internal form (JVMS 4.2.1);
identifiers are separated by forward slashes rather than periods.
</description>
</param>
<param id="module_ptr">
<outptr><jobject/></outptr>
<description>
On return, points to a <code>java.lang.reflect.Module</code> object
or points to <code>NULL</code>.
</description>
</param>
</parameters>
<errors>
<error id="JVMTI_ERROR_ILLEGAL_ARGUMENT">
If class loader is not <code>NULL</code> and is not a class loader object.
</error>
</errors>
</function>
</category>
<category id="class" label="Class">
@ -12462,6 +12515,14 @@ myInit() {
<code>new_class_data</code> has been set, it becomes the
<code>class_data</code> for the next agent.
<p/>
When handling a class load in the live phase, then the
<functionlink id="GetNamedModule"></functionlink>
function can be used to map class loader and a package name to a module.
When a class is being redefined or retransformed then
<code>class_being_redefined</code> is non <code>NULL</code> and so
the JNI <code>GetModule</code> function can also be used
to obtain the Module.
<p/>
The order that this event is sent to each environment differs
from other events.
This event is sent to environments in the following order:
@ -14427,20 +14488,15 @@ typedef void (JNICALL *jvmtiEventVMInit)
<change date="19 June 2013" version="1.2.3">
Added support for statically linked agents.
</change>
<change date="20 January 2016" version="9.0.0">
<change date="5 July 2016" version="9.0.0">
Support for modules:
- The majorversion is 9 now
- The ClassFileLoadHook events are not sent during the primordial phase anymore.
- Add new function GetAllModules
</change>
<change date="17 February 2016" version="9.0.0">
Support for modules:
- Add new capability can_generate_early_vmstart
- Allow CompiledMethodLoad events at start phase
</change>
<change date="14 April 2016" version="9.0.0">
Support for modules:
- Add new capability can_generate_early_class_hook_events
- Add new function GetNamedModule
</change>
</changehistory>

View File

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "classfile/classLoaderExt.hpp"
#include "classfile/modules.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "interpreter/bytecodeStream.hpp"
@ -201,6 +202,28 @@ JvmtiEnv::GetAllModules(jint* module_count_ptr, jobject** modules_ptr) {
} /* end GetAllModules */
// class_loader - NULL is a valid value, must be pre-checked
// package_name - pre-checked for NULL
// module_ptr - pre-checked for NULL
jvmtiError
JvmtiEnv::GetNamedModule(jobject class_loader, const char* package_name, jobject* module_ptr) {
JavaThread* THREAD = JavaThread::current(); // pass to macros
ResourceMark rm(THREAD);
Handle h_loader (THREAD, JNIHandles::resolve(class_loader));
// Check that loader is a subclass of java.lang.ClassLoader.
if (h_loader.not_null() && !java_lang_ClassLoader::is_subclass(h_loader->klass())) {
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
}
jobject module = Modules::get_named_module(h_loader, package_name, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
return JVMTI_ERROR_INTERNAL; // unexpected exception
}
*module_ptr = module;
return JVMTI_ERROR_NONE;
} /* end GetNamedModule */
//
// Class functions
//

View File

@ -131,8 +131,6 @@ static int Knob_MoveNotifyee = 2; // notify() - disposition of noti
static int Knob_QMode = 0; // EntryList-cxq policy - queue discipline
static volatile int InitDone = 0;
#define TrySpin TrySpin_VaryDuration
// -----------------------------------------------------------------------------
// Theory of operations -- Monitors lists, thread residency, etc:
//
@ -1848,13 +1846,8 @@ void ObjectMonitor::notifyAll(TRAPS) {
// hysteresis control to damp the transition rate between spinning and
// not spinning.
intptr_t ObjectMonitor::SpinCallbackArgument = 0;
int (*ObjectMonitor::SpinCallbackFunction)(intptr_t, int) = NULL;
// Spinning: Fixed frequency (100%), vary duration
int ObjectMonitor::TrySpin_VaryDuration(Thread * Self) {
int ObjectMonitor::TrySpin(Thread * Self) {
// Dumb, brutal spin. Good for comparative measurements against adaptive spinning.
int ctr = Knob_FixedSpin;
if (ctr != 0) {
@ -1948,11 +1941,6 @@ int ObjectMonitor::TrySpin_VaryDuration(Thread * Self) {
goto Abort; // abrupt spin egress
}
if (Knob_UsePause & 1) SpinPause();
int (*scb)(intptr_t,int) = SpinCallbackFunction;
if (hits > 50 && scb != NULL) {
int abend = (*scb)(SpinCallbackArgument, 0);
}
}
if (Knob_UsePause & 2) SpinPause();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2016, 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
@ -161,9 +161,6 @@ class ObjectMonitor {
Thread * volatile _Responsible;
volatile int _Spinner; // for exit->spinner handoff optimization
volatile int _SpinFreq; // Spin 1-out-of-N attempts: success rate
volatile int _SpinClock;
volatile intptr_t _SpinState; // MCS/CLH list of spinners
volatile int _SpinDuration;
volatile jint _count; // reference count to prevent reclamation/deflation
@ -238,10 +235,6 @@ class ObjectMonitor {
static int cxq_offset_in_bytes() { return offset_of(ObjectMonitor, _cxq); }
static int succ_offset_in_bytes() { return offset_of(ObjectMonitor, _succ); }
static int EntryList_offset_in_bytes() { return offset_of(ObjectMonitor, _EntryList); }
static int FreeNext_offset_in_bytes() { return offset_of(ObjectMonitor, FreeNext); }
static int WaitSet_offset_in_bytes() { return offset_of(ObjectMonitor, _WaitSet); }
static int Responsible_offset_in_bytes() { return offset_of(ObjectMonitor, _Responsible); }
static int Spinner_offset_in_bytes() { return offset_of(ObjectMonitor, _Spinner); }
// ObjectMonitor references can be ORed with markOopDesc::monitor_value
// as part of the ObjectMonitor tagging mechanism. When we combine an
@ -257,11 +250,6 @@ class ObjectMonitor {
#define OM_OFFSET_NO_MONITOR_VALUE_TAG(f) \
((ObjectMonitor::f ## _offset_in_bytes()) - markOopDesc::monitor_value)
// Eventually we'll make provisions for multiple callbacks, but
// now one will suffice.
static int (*SpinCallbackFunction)(intptr_t, int);
static intptr_t SpinCallbackArgument;
markOop header() const;
void set_header(markOop hdr);
@ -312,8 +300,6 @@ class ObjectMonitor {
_cxq = NULL;
_WaitSet = NULL;
_recursions = 0;
_SpinFreq = 0;
_SpinClock = 0;
}
public:
@ -353,9 +339,7 @@ class ObjectMonitor {
void UnlinkAfterAcquire(Thread * Self, ObjectWaiter * SelfNode);
int TryLock(Thread * Self);
int NotRunnable(Thread * Self, Thread * Owner);
int TrySpin_Fixed(Thread * Self);
int TrySpin_VaryFrequency(Thread * Self);
int TrySpin_VaryDuration(Thread * Self);
int TrySpin(Thread * Self);
void ExitEpilog(Thread * Self, ObjectWaiter * Wakee);
bool ExitSuspendEquivalent(JavaThread * Self);
void post_monitor_wait_event(EventJavaMonitorWait * event,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2016, 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
@ -144,8 +144,6 @@ class ObjectSynchronizer : AllStatic {
static void verify() PRODUCT_RETURN;
static int verify_objmon_isinpool(ObjectMonitor *addr) PRODUCT_RETURN0;
static void RegisterSpinCallback(int(*)(intptr_t, int), intptr_t);
private:
enum { _BLOCKSIZE = 128 };
// global list of blocks of monitors

View File

@ -29,6 +29,7 @@
## @summary testing of ciReplay with using generated by VM replay.txt w/o comp_level
## @author igor.ignatyev@oracle.com
## @requires vm.flightRecorder != true
## @ignore 8157984
## @run shell TestVM_no_comp_level.sh
##

View File

@ -28,6 +28,7 @@
* @library /testlibrary /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
* @ignore 8157984
* @build TestRangeCheckSmearing
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* jdk.test.lib.Platform

View File

@ -26,6 +26,7 @@
* @library /testlibrary /test/lib /
* @modules java.base/jdk.internal.misc
* @modules java.management
* @ignore 8157984
* @build NonTieredLevelsTest
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2015, 2016, 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 TestInitialGCThreadLogging
* @bug 8157240
* @summary Check trace logging of initial GC threads.
* @requires vm.gc=="null"
* @key gc
* @modules java.base/jdk.internal.misc
* @library /testlibrary
*/
import jdk.test.lib.ProcessTools;
import jdk.test.lib.OutputAnalyzer;
public class TestInitialGCThreadLogging {
public static void main(String[] args) throws Exception {
testInitialGCThreadLogging("UseConcMarkSweepGC", "GC Thread");
testInitialGCThreadLogging("UseG1GC", "GC Thread");
testInitialGCThreadLogging("UseParallelGC", "ParGC Thread");
}
private static void verifyDynamicNumberOfGCThreads(OutputAnalyzer output, String threadName) {
output.shouldHaveExitValue(0); // test should run succesfully
output.shouldContain(threadName);
}
private static void testInitialGCThreadLogging(String gcFlag, String threadName) throws Exception {
// UseDynamicNumberOfGCThreads and TraceDynamicGCThreads enabled
String[] baseArgs = {"-XX:+" + gcFlag, "-Xmx10M", "-XX:+UseDynamicNumberOfGCThreads", "-Xlog:gc+task=trace", "-version"};
// Base test with gc and +UseDynamicNumberOfGCThreads:
ProcessBuilder pb_enabled = ProcessTools.createJavaProcessBuilder(baseArgs);
verifyDynamicNumberOfGCThreads(new OutputAnalyzer(pb_enabled.start()), threadName);
}
}

View File

@ -46,7 +46,7 @@ public class TestStringSymbolTableStats {
System.out.println("Output:\n" + output.getOutput());
output.shouldContain("Cleaned string and symbol table");
output.shouldMatch("GC\\(\\d+\\) Cleaned string and symbol table");
output.shouldHaveExitValue(0);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 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
@ -24,11 +24,11 @@
import java.util.ArrayList;
/* @test TestMetaspaceInitialization
* @bug 8042933
* @bug 8024945
* @summary Tests to initialize metaspace with a very low MetaspaceSize
* @modules java.base/jdk.internal.misc
* @library /testlibrary
* @run main/othervm -XX:MetaspaceSize=2m TestMetaspaceInitialization
* @run main/othervm -XX:MetaspaceSize=0 TestMetaspaceInitialization
*/
public class TestMetaspaceInitialization {
private class Internal {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2016, 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
@ -47,9 +47,6 @@ public class TestMetaspaceSizeFlags {
// 8024650: MaxMetaspaceSize was adjusted instead of MetaspaceSize.
testMaxMetaspaceSizeLTMetaspaceSize(MAX_ALIGNMENT, MAX_ALIGNMENT * 2);
testMaxMetaspaceSizeGTMetaspaceSize(MAX_ALIGNMENT * 2, MAX_ALIGNMENT);
testTooSmallInitialMetaspace(0, 0);
testTooSmallInitialMetaspace(0, MAX_ALIGNMENT);
testTooSmallInitialMetaspace(MAX_ALIGNMENT, 0);
}
private static void testMaxMetaspaceSizeEQMetaspaceSize(long maxMetaspaceSize, long metaspaceSize) throws Exception {
@ -73,11 +70,6 @@ public class TestMetaspaceSizeFlags {
Asserts.assertEQ(mf.metaspaceSize, metaspaceSize);
}
private static void testTooSmallInitialMetaspace(long maxMetaspaceSize, long metaspaceSize) throws Exception {
OutputAnalyzer output = run(maxMetaspaceSize, metaspaceSize);
output.shouldContain("Too small initial Metaspace size");
}
private static MetaspaceFlags runAndGetValue(long maxMetaspaceSize, long metaspaceSize) throws Exception {
OutputAnalyzer output = run(maxMetaspaceSize, metaspaceSize);
output.shouldNotMatch("Error occurred during initialization of VM\n.*");

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2016, 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.
*
*/
public class TestPutField
version 53:0
{
final Field test_field:"I";
public Method <init>:"()V"
stack 2 locals 1
{
aload_0;
dup;
invokespecial Method java/lang/Object.<init>:"()V";
bipush 13;
putfield Field test_field:"I";
return;
}
public Method aMethod:"()I"
stack 2 locals 2
{
aload_0;
getfield Field test_field:"I";
istore_1;
aload_0;
bipush 14;
putfield Field test_field:"I";
iload_1;
ireturn;
}
public static Method test:"()V"
stack 2 locals 2
{
new class TestPutField;
astore_0;
aload_0;
invokespecial Method <init>:"()V";
getstatic Field java/lang/System.out:"Ljava/io/PrintStream;";
astore_1;
aload_1;
aload_0;
invokevirtual Method aMethod:"()I";
invokevirtual Method java/io/PrintStream.println:"(I)V";
aload_1;
aload_0;
getfield Field test_field:"I";
invokevirtual Method java/io/PrintStream.println:"(I)V";
return;
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2016, 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 8160527
* @summary The VM does not always perform checks added by 8157181 when updating final instance fields
* @library /testlibrary
* @compile TestPutField.jasm
* @compile TestPutStatic.jasm
* @compile TestPutMain.java
* @run main/othervm TestPutMain
*/
import jdk.test.lib.Asserts;
public class TestPutMain {
public static void main(String[] args) {
boolean exception = false;
try {
TestPutField.test();
} catch (java.lang.IllegalAccessError e) {
exception = true;
}
Asserts.assertTrue(exception, "FAILED: Expected IllegalAccessError for illegal update to final instance field was not thrown.");
exception = false;
try {
TestPutStatic.test();
} catch (java.lang.IllegalAccessError e) {
exception = true;
}
Asserts.assertTrue(exception, "FAILED: Expected IllegalAccessError for illegal update to final static field was not thrown.");
System.out.println("PASSED: Expected IllegalAccessError was thrown.");
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2016, 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.
*
*/
public class TestPutStatic
version 53:0
{
final static Field test_field:"I";
public static Method <clinit>:"()V"
stack 2 locals 1
{
bipush 13;
putstatic Field test_field:"I";
return;
}
public static Method aMethod:"()I"
stack 1 locals 1
{
getstatic Field test_field:"I";
istore_0;
bipush 14;
putstatic Field test_field:"I";
iload_0;
ireturn;
}
public static Method test:"()V"
stack 2 locals 1
{
getstatic Field java/lang/System.out:"Ljava/io/PrintStream;";
astore_0;
aload_0;
invokestatic Method aMethod:"()I";
invokevirtual Method java/io/PrintStream.println:"(I)V";
aload_0;
getstatic Field test_field:"I";
invokevirtual Method java/io/PrintStream.println:"(I)V";
return;
}
}

View File

@ -24,6 +24,9 @@
/*
* @test SASymbolTableTest
* @summary Walk symbol table using SA, with and without CDS.
* Started failing on 2016.06.24 due to 8160376 on MacOS X so quarantine
* it on that platform:
* @requires os.family != "mac"
* @library /testlibrary
* @modules java.base/jdk.internal.misc
* jdk.hotspot.agent/sun.jvm.hotspot.oops

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2016, 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 MyPackage;
/**
* @test
* @summary Verifies the JVMTI GetNamedModule API
* @compile GetNamedModuleTest.java
* @run main/othervm/native -agentlib:GetNamedModuleTest MyPackage.GetNamedModuleTest
*/
import java.io.PrintStream;
public class GetNamedModuleTest {
static {
try {
System.loadLibrary("GetNamedModuleTest");
} catch (UnsatisfiedLinkError ule) {
System.err.println("Could not load GetNamedModuleTest library");
System.err.println("java.library.path: "
+ System.getProperty("java.library.path"));
throw ule;
}
}
native static int check();
public static void main(String args[]) {
int status = check();
if (status != 0) {
throw new RuntimeException("Non-zero status returned from the agent: " + status);
}
}
}

View File

@ -0,0 +1,405 @@
/*
* Copyright (c) 2016, 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.
*/
#include <stdio.h>
#include <string.h>
#include "jvmti.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef JNI_ENV_ARG
#ifdef __cplusplus
#define JNI_ENV_ARG(x, y) y
#define JNI_ENV_PTR(x) x
#else
#define JNI_ENV_ARG(x,y) x, y
#define JNI_ENV_PTR(x) (*x)
#endif
#endif
#define TranslateError(err) "JVMTI error"
#define PASSED 0
#define FAILED 2
static const char *EXC_CNAME = "java/lang/Exception";
static const char* MOD_CNAME = "Ljava/lang/reflect/Module;";
static jvmtiEnv *jvmti = NULL;
static jint result = PASSED;
static jboolean printdump = JNI_FALSE;
static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
JNIEXPORT
jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
return Agent_Initialize(jvm, options, reserved);
}
JNIEXPORT
jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
return Agent_Initialize(jvm, options, reserved);
}
JNIEXPORT
jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
return JNI_VERSION_1_8;
}
static
jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
jint res;
if (options != NULL && strcmp(options, "printdump") == 0) {
printdump = JNI_TRUE;
}
res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
JVMTI_VERSION_9);
if (res != JNI_OK || jvmti == NULL) {
printf(" Error: wrong result of a valid call to GetEnv!\n");
return JNI_ERR;
}
return JNI_OK;
}
static
jint throw_exc(JNIEnv *env, char *msg) {
jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME));
if (exc_class == NULL) {
printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME);
return -1;
}
return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
}
static
jobject get_class_loader(jclass cls) {
jvmtiError err = JVMTI_ERROR_NONE;
jobject loader = NULL;
if (printdump == JNI_TRUE) {
printf(">>> getting class loader ...\n");
}
err = (*jvmti)->GetClassLoader(jvmti, cls, &loader);
if (err != JVMTI_ERROR_NONE) {
printf(" Error in GetClassLoader: %s (%d)\n", TranslateError(err), err);
}
return loader;
}
static
jclass jlrM(JNIEnv *env) {
jclass cls = NULL;
cls = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, MOD_CNAME));
if (cls == NULL) {
printf(" Error in JNI FindClass: %s\n", MOD_CNAME);
}
return cls;
}
jmethodID
get_method(JNIEnv *env, jclass clazz, const char * name, const char *sig) {
jmethodID method = NULL;
method = JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG(env, clazz), name, sig);
if (method == NULL) {
printf(" Error in JNI GetMethodID %s with signature %s", name, sig);
}
return method;
}
static
jobject get_module_loader(JNIEnv *env, jobject module) {
static jmethodID cl_method = NULL;
jobject loader = NULL;
if (cl_method == NULL) {
cl_method = get_method(env, jlrM(env), "getClassLoader", "()Ljava/lang/ClassLoader;");
}
loader = (jobject)JNI_ENV_PTR(env)->CallObjectMethod(JNI_ENV_ARG(env, module), cl_method);
return loader;
}
static
const char* get_module_name(JNIEnv *env, jobject module) {
static jmethodID method = NULL;
jobject loader = NULL;
jstring jstr = NULL;
const char *name = NULL;
const char *nstr = NULL;
if (method == NULL) {
method = get_method(env, jlrM(env), "getName", "()Ljava/lang/String;");
}
jstr = (jstring)JNI_ENV_PTR(env)->CallObjectMethod(JNI_ENV_ARG(env, module), method);
if (jstr != NULL) {
name = JNI_ENV_PTR(env)->GetStringUTFChars(JNI_ENV_ARG(env, jstr), NULL);
}
loader = get_module_loader(env, module);
nstr = (name == NULL) ? "<UNNAMED>" : name;
printf(" loader: %p, module: %p, name: %s\n", loader, module, nstr);
return name;
}
static
jvmtiError get_module(JNIEnv *env,
jobject loader,
const char* pkg_name,
jobject* module_ptr,
const char** mod_name_ptr) {
jvmtiError err = JVMTI_ERROR_NONE;
const char* name = (pkg_name == NULL) ? "<NULL>" : pkg_name;
printf(">>> getting module by loader %p and package \"%s\"\n", loader, name);
*mod_name_ptr = NULL;
err = (*jvmti)->GetNamedModule(jvmti, loader, pkg_name, module_ptr);
if (err != JVMTI_ERROR_NONE) {
printf(" Error in GetNamedModule for package \"%s\": %s (%d)\n",
pkg_name, TranslateError(err), err);
return err;
}
printf(" returned module: %p\n", *module_ptr);
if (*module_ptr == NULL) { // named module was not found
return err;
}
*mod_name_ptr = get_module_name(env, *module_ptr);
return err;
}
static
jint get_all_modules(JNIEnv *env) {
jvmtiError err;
jint cnt = -1;
jint idx = 0;
jobject* modules;
printf(">>> Inspecting modules with GetAllModules\n");
err = (*jvmti)->GetAllModules(jvmti, &cnt, &modules);
if (err != JVMTI_ERROR_NONE) {
printf("Error in GetAllModules: %d\n", err);
return -1;
}
for (idx = 0; idx < cnt; ++idx) {
get_module_name(env, modules[idx]);
}
return cnt;
}
static
jint check_bad_loader(JNIEnv *env, jobject loader) {
jvmtiError err = JVMTI_ERROR_NONE;
jobject module = NULL;
const char* mod_name = NULL;
err = get_module(env, loader, "", &module, &mod_name);
if (err != JVMTI_ERROR_ILLEGAL_ARGUMENT) {
return FAILED;
}
printf(" got expected JVMTI_ERROR_ILLEGAL_ARGUMENT for bad loader\n");
return PASSED;
}
static
jint check_system_loader(JNIEnv *env, jobject loader) {
jvmtiError err = JVMTI_ERROR_NONE;
jobject module = NULL;
const char* exp_name = NULL;
const char* mod_name = NULL;
// NULL pointer for package name
err = get_module(env, loader, NULL, &module, &mod_name);
if (err != JVMTI_ERROR_NULL_POINTER) {
throw_exc(env, "check #SN1: failed to return JVMTI_ERROR_NULL_POINTER for NULL package");
return FAILED;
}
// NULL pointer for module_ptr
err = (*jvmti)->GetNamedModule(jvmti, loader, "", NULL);
if (err != JVMTI_ERROR_NULL_POINTER) {
throw_exc(env, "check #SN2: failed to return JVMTI_ERROR_NULL_POINTER for NULL module_ptr");
return FAILED;
}
// Unnamed/default package ""
err = get_module(env, loader, "", &module, &mod_name);
if (err != JVMTI_ERROR_NONE) {
throw_exc(env, "check #S1: failed to return JVMTI_ERROR_NONE for default package");
return FAILED;
}
if (module != NULL || mod_name != NULL) {
throw_exc(env, "check #S2: failed to return NULL-module for default package");
return FAILED;
}
// Test package: MyPackage
err = get_module(env, loader, "MyPackage", &module, &mod_name);
if (err != JVMTI_ERROR_NONE) {
throw_exc(env, "check #S3: failed to return JVMTI_ERROR_NONE for MyPackage");
return FAILED;
}
if (module != NULL || mod_name != NULL) {
throw_exc(env, "check #S4: failed to return NULL-module for MyPackage");
return FAILED;
}
// Package: com/sun/jdi
exp_name = "jdk.jdi";
err = get_module(env, loader, "com/sun/jdi", &module, &mod_name);
if (err != JVMTI_ERROR_NONE) {
throw_exc(env, "check #S5: failed to return JVMTI_ERROR_NONE for test package");
return FAILED;
}
if (module == NULL || mod_name == NULL) {
throw_exc(env, "check #S6: failed to return named module for com/sun/jdi package");
return FAILED;
}
if (strcmp(mod_name, exp_name) != 0) {
printf("check #S7: failed to return right module, expected: %s, returned: %s\n",
exp_name, mod_name);
throw_exc(env, "check #S7: failed to return jdk.jdi module for com/sun/jdi package");
return FAILED;
}
// Non-existing package: "bad/package/name"
err = get_module(env, loader, "bad/package/name", &module, &mod_name);
if (err != JVMTI_ERROR_NONE) {
throw_exc(env, "check #S8: failed to return JVMTI_ERROR_NONE for bad package");
return FAILED;
}
if (module != NULL || mod_name != NULL) {
throw_exc(env, "check #S9: failed to return NULL-module for bad package");
return FAILED;
}
return PASSED;
}
static
jint check_bootstrap_loader(JNIEnv *env, jobject loader) {
jvmtiError err = JVMTI_ERROR_NONE;
jobject module = NULL;
const char* exp_name = NULL;
const char* mod_name = NULL;
// NULL pointer for package name
err = get_module(env, loader, NULL, &module, &mod_name);
if (err != JVMTI_ERROR_NULL_POINTER) {
throw_exc(env, "check #BN1: failed to return JVMTI_ERROR_NULL_POINTER for NULL package");
return FAILED;
}
// NULL pointer for module_ptr
err = (*jvmti)->GetNamedModule(jvmti, loader, "", NULL);
if (err != JVMTI_ERROR_NULL_POINTER) {
throw_exc(env, "check #BN2: failed to return JVMTI_ERROR_NULL_POINTER for NULL module_ptr");
return FAILED;
}
// Unnamed/default package ""
err = get_module(env, loader, "", &module, &mod_name);
if (err != JVMTI_ERROR_NONE) {
throw_exc(env, "check #B1: failed to return JVMTI_ERROR_NONE for default package");
return FAILED;
}
if (module != NULL || mod_name != NULL) {
throw_exc(env, "check #B2: failed to return NULL-module for default package");
return FAILED;
}
// Normal package from java.base module: "java/lang"
exp_name = "java.base";
err = get_module(env, loader, "java/lang", &module, &mod_name);
if (err != JVMTI_ERROR_NONE) {
throw_exc(env, "check #B3: failed to return JVMTI_ERROR_NONE for java/lang package");
return FAILED;
}
if (module == NULL || mod_name == NULL) {
throw_exc(env, "check #B4: failed to return named module for java/lang package");
return FAILED;
}
if (strcmp(exp_name, mod_name) != 0) {
printf("check #B5: failed to return right module, expected: %s, returned: %s\n",
exp_name, mod_name);
throw_exc(env, "check #B5: failed to return expected module for java/lang package");
return FAILED;
}
// Non-existing package: "bad/package/name"
err = get_module(env, loader, "bad/package/name", &module, &mod_name);
if (err != JVMTI_ERROR_NONE) {
throw_exc(env, "check #B6: failed to return JVMTI_ERROR_NONE for bad package");
return FAILED;
}
if (module != NULL || mod_name != NULL) {
throw_exc(env, "check #B7: failed to return NULL-module for bad package");
return FAILED;
}
return PASSED;
}
JNIEXPORT jint JNICALL
Java_MyPackage_GetNamedModuleTest_check(JNIEnv *env, jclass cls) {
jobject loader = NULL;
if (jvmti == NULL) {
throw_exc(env, "JVMTI client was not properly loaded!\n");
return FAILED;
}
get_all_modules(env);
printf("\n*** Check for bad ClassLoader ***\n\n");
result = check_bad_loader(env, (jobject)cls);
if (result != PASSED) {
throw_exc(env, "check #L1: failed to return JVMTI_ERROR_ILLEGAL_ARGUMENT for bad loader");
return result;
}
loader = get_class_loader(cls);
if (loader == NULL) {
throw_exc(env, "check #L2: failed to return non-NULL loader for valid test class");
return FAILED;
}
printf("\n*** Checks for System ClassLoader ***\n\n");
result = check_system_loader(env, loader);
if (result != PASSED) {
return result;
}
printf("\n*** Checks for Bootstrap ClassLoader ***\n\n");
result = check_bootstrap_loader(env, NULL);
return result;
}
#ifdef __cplusplus
}
#endif

View File

@ -32,6 +32,9 @@ import jdk.test.lib.apps.LingeredApp;
/*
* @test
* @summary Started failing on 2016.06.24 due to 8160376 on MacOS X so
* quarantine it on that platform:
* @requires os.family != "mac"
* @modules java.base/jdk.internal.misc
* @library /test/lib/share/classes
* @library /testlibrary

View File

@ -32,6 +32,9 @@ import jdk.test.lib.apps.LingeredApp;
/*
* @test
* @summary Started failing on 2016.06.24 due to 8160376 on MacOS X so
* quarantine it on that platform:
* @requires os.family != "mac"
* @modules java.base/jdk.internal.misc
* @library /test/lib/share/classes
* @library /testlibrary

View File

@ -43,6 +43,9 @@ import jdk.test.lib.ProcessTools;
* @bug 6313383
* @key regression
* @summary Regression test for hprof export issue due to large heaps (>2G)
* Started failing on 2016.06.24 due to 8160376 on MacOS X so quarantine
* it on that platform:
* @requires os.family != "mac"
* @library /testlibrary
* @modules java.base/jdk.internal.misc
* java.compiler