--- a/hotspot/src/os/windows/vm/os_windows.cpp Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Tue Sep 27 20:55:13 2016 -0400
@@ -2366,7 +2366,9 @@
if (Interpreter::contains(pc)) {
*fr = os::fetch_frame_from_context((void*)exceptionInfo->ContextRecord);
if (!fr->is_first_java_frame()) {
- assert(fr->safe_for_sender(thread), "Safety check");
+ // get_frame_at_stack_banging_point() is only called when we
+ // have well defined stacks so java_sender() calls do not need
+ // to assert safe_for_sender() first.
*fr = fr->java_sender();
}
} else {
@@ -2383,7 +2385,7 @@
// has been pushed on the stack
*fr = frame(fr->sp() + 1, fr->fp(), (address)*(fr->sp()));
if (!fr->is_java_frame()) {
- assert(fr->safe_for_sender(thread), "Safety check");
+ // See java_sender() comment above.
*fr = fr->java_sender();
}
}
--- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Tue Sep 27 20:55:13 2016 -0400
@@ -378,7 +378,9 @@
// method returns the Java sender of the current frame.
*fr = os::fetch_frame_from_ucontext(thread, uc);
if (!fr->is_first_java_frame()) {
- assert(fr->safe_for_sender(thread), "Safety check");
+ // get_frame_at_stack_banging_point() is only called when we
+ // have well defined stacks so java_sender() calls do not need
+ // to assert safe_for_sender() first.
*fr = fr->java_sender();
}
} else {
@@ -395,7 +397,7 @@
// has been pushed on the stack
*fr = frame(fr->sp() + 1, fr->fp(), (address)*(fr->sp()));
if (!fr->is_java_frame()) {
- assert(fr->safe_for_sender(thread), "Safety check");
+ // See java_sender() comment above.
*fr = fr->java_sender();
}
}
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Tue Sep 27 20:55:13 2016 -0400
@@ -191,7 +191,9 @@
// method returns the Java sender of the current frame.
*fr = os::fetch_frame_from_ucontext(thread, uc);
if (!fr->is_first_java_frame()) {
- assert(fr->safe_for_sender(thread), "Safety check");
+ // get_frame_at_stack_banging_point() is only called when we
+ // have well defined stacks so java_sender() calls do not need
+ // to assert safe_for_sender() first.
*fr = fr->java_sender();
}
} else {
@@ -209,8 +211,8 @@
intptr_t* sp = os::Linux::ucontext_get_sp(uc);
*fr = frame(sp + 1, fp, (address)*sp);
if (!fr->is_java_frame()) {
- assert(fr->safe_for_sender(thread), "Safety check");
assert(!fr->is_first_frame(), "Safety check");
+ // See java_sender() comment above.
*fr = fr->java_sender();
}
}
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Tue Sep 27 20:55:13 2016 -0400
@@ -255,7 +255,9 @@
// method returns the Java sender of the current frame.
*fr = os::fetch_frame_from_ucontext(thread, uc);
if (!fr->is_first_java_frame()) {
- assert(fr->safe_for_sender(thread), "Safety check");
+ // get_frame_at_stack_banging_point() is only called when we
+ // have well defined stacks so java_sender() calls do not need
+ // to assert safe_for_sender() first.
*fr = fr->java_sender();
}
} else {
@@ -273,7 +275,7 @@
intptr_t* sp = os::Solaris::ucontext_get_sp(uc);
*fr = frame(sp + 1, fp, (address)*sp);
if (!fr->is_java_frame()) {
- assert(fr->safe_for_sender(thread), "Safety check");
+ // See java_sender() comment above.
*fr = fr->java_sender();
}
}
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp Tue Sep 27 20:55:13 2016 -0400
@@ -540,7 +540,7 @@
// Overflow list of grey objects, threaded through mark-word
// Manipulated with CAS in the parallel/multi-threaded case.
- oop _overflow_list;
+ oopDesc* volatile _overflow_list;
// The following array-pair keeps track of mark words
// displaced for accommodating overflow list above.
// This code will likely be revisited under RFE#4922830.
--- a/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp Tue Sep 27 20:55:13 2016 -0400
@@ -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
@@ -323,7 +323,7 @@
// A list of from-space images of to-be-scanned objects, threaded through
// klass-pointers (klass information already copied to the forwarded
// image.) Manipulated with CAS.
- oop _overflow_list;
+ oopDesc* volatile _overflow_list;
NOT_PRODUCT(ssize_t _num_par_pushes;)
// This closure is used by the reference processor to filter out
--- a/hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp Tue Sep 27 20:55:13 2016 -0400
@@ -81,47 +81,6 @@
_last_marking_length_s(0.0) {
}
-#ifndef PRODUCT
-static void test_update(G1IHOPControl* ctrl, double alloc_time, size_t alloc_amount, size_t young_size, double mark_time) {
- for (int i = 0; i < 100; i++) {
- ctrl->update_allocation_info(alloc_time, alloc_amount, young_size);
- ctrl->update_marking_length(mark_time);
- }
-}
-
-void G1StaticIHOPControl::test() {
- size_t const initial_ihop = 45;
-
- G1StaticIHOPControl ctrl(initial_ihop);
- ctrl.update_target_occupancy(100);
-
- size_t threshold = ctrl.get_conc_mark_start_threshold();
- assert(threshold == initial_ihop,
- "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold);
-
- ctrl.update_allocation_info(100.0, 100, 100);
- threshold = ctrl.get_conc_mark_start_threshold();
- assert(threshold == initial_ihop,
- "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold);
-
- ctrl.update_marking_length(1000.0);
- threshold = ctrl.get_conc_mark_start_threshold();
- assert(threshold == initial_ihop,
- "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold);
-
- // Whatever we pass, the IHOP value must stay the same.
- test_update(&ctrl, 2, 10, 10, 3);
- threshold = ctrl.get_conc_mark_start_threshold();
- assert(threshold == initial_ihop,
- "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold);
-
- test_update(&ctrl, 12, 10, 10, 3);
- threshold = ctrl.get_conc_mark_start_threshold();
- assert(threshold == initial_ihop,
- "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold);
-}
-#endif
-
G1AdaptiveIHOPControl::G1AdaptiveIHOPControl(double ihop_percent,
G1Predictions const* predictor,
size_t heap_reserve_percent,
@@ -224,79 +183,3 @@
_predictor->get_new_prediction(&_marking_times_s),
have_enough_data_for_prediction());
}
-
-#ifndef PRODUCT
-void G1AdaptiveIHOPControl::test() {
- size_t const initial_threshold = 45;
- size_t const young_size = 10;
- size_t const target_size = 100;
-
- // The final IHOP value is always
- // target_size - (young_size + alloc_amount/alloc_time * marking_time)
-
- G1Predictions pred(0.95);
- G1AdaptiveIHOPControl ctrl(initial_threshold, &pred, 0, 0);
- ctrl.update_target_occupancy(target_size);
-
- // First "load".
- size_t const alloc_time1 = 2;
- size_t const alloc_amount1 = 10;
- size_t const marking_time1 = 2;
- size_t const settled_ihop1 = target_size - (young_size + alloc_amount1/alloc_time1 * marking_time1);
-
- size_t threshold;
- threshold = ctrl.get_conc_mark_start_threshold();
- assert(threshold == initial_threshold,
- "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_threshold, threshold);
- for (size_t i = 0; i < G1AdaptiveIHOPNumInitialSamples - 1; i++) {
- ctrl.update_allocation_info(alloc_time1, alloc_amount1, young_size);
- ctrl.update_marking_length(marking_time1);
- // Not enough data yet.
- threshold = ctrl.get_conc_mark_start_threshold();
- assert(threshold == initial_threshold,
- "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_threshold, threshold);
- }
-
- test_update(&ctrl, alloc_time1, alloc_amount1, young_size, marking_time1);
-
- threshold = ctrl.get_conc_mark_start_threshold();
- assert(threshold == settled_ihop1,
- "Expected IHOP threshold to settle at " SIZE_FORMAT " but is " SIZE_FORMAT, settled_ihop1, threshold);
-
- // Second "load". A bit higher allocation rate.
- size_t const alloc_time2 = 2;
- size_t const alloc_amount2 = 30;
- size_t const marking_time2 = 2;
- size_t const settled_ihop2 = target_size - (young_size + alloc_amount2/alloc_time2 * marking_time2);
-
- test_update(&ctrl, alloc_time2, alloc_amount2, young_size, marking_time2);
-
- threshold = ctrl.get_conc_mark_start_threshold();
- assert(threshold < settled_ihop1,
- "Expected IHOP threshold to settle at a value lower than " SIZE_FORMAT " but is " SIZE_FORMAT, settled_ihop1, threshold);
-
- // Third "load". Very high (impossible) allocation rate.
- size_t const alloc_time3 = 1;
- size_t const alloc_amount3 = 50;
- size_t const marking_time3 = 2;
- size_t const settled_ihop3 = 0;
-
- test_update(&ctrl, alloc_time3, alloc_amount3, young_size, marking_time3);
- threshold = ctrl.get_conc_mark_start_threshold();
-
- assert(threshold == settled_ihop3,
- "Expected IHOP threshold to settle at " SIZE_FORMAT " but is " SIZE_FORMAT, settled_ihop3, threshold);
-
- // And back to some arbitrary value.
- test_update(&ctrl, alloc_time2, alloc_amount2, young_size, marking_time2);
-
- threshold = ctrl.get_conc_mark_start_threshold();
- assert(threshold > settled_ihop3,
- "Expected IHOP threshold to settle at value larger than " SIZE_FORMAT " but is " SIZE_FORMAT, settled_ihop3, threshold);
-}
-
-void IHOP_test() {
- G1StaticIHOPControl::test();
- G1AdaptiveIHOPControl::test();
-}
-#endif
--- a/hotspot/src/share/vm/gc/g1/g1IHOPControl.hpp Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1IHOPControl.hpp Tue Sep 27 20:55:13 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -99,10 +99,6 @@
assert(marking_length_s > 0.0, "Marking length must be larger than zero but is %.3f", marking_length_s);
_last_marking_length_s = marking_length_s;
}
-
-#ifndef PRODUCT
- static void test();
-#endif
};
// This algorithm tries to return a concurrent mark starting occupancy value that
@@ -148,9 +144,6 @@
virtual void print();
virtual void send_trace_event(G1NewTracer* tracer);
-#ifndef PRODUCT
- static void test();
-#endif
};
#endif // SHARE_VM_GC_G1_G1IHOPCONTROL_HPP
--- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp Tue Sep 27 20:55:13 2016 -0400
@@ -668,20 +668,18 @@
// fail arbitrarily). We tell the iteration code to perform this
// filtering when it has been determined that there has been an actual
// allocation in this region and making it safe to check the young type.
- bool filter_young = true;
- HeapWord* stop_point =
+ bool card_processed =
r->oops_on_card_seq_iterate_careful(dirtyRegion,
&filter_then_update_rs_oop_cl,
- filter_young,
card_ptr);
- // If stop_point is non-null, then we encountered an unallocated region
- // (perhaps the unfilled portion of a TLAB.) For now, we'll dirty the
- // card and re-enqueue: if we put off the card until a GC pause, then the
- // unallocated portion will be filled in. Alternatively, we might try
- // the full complexity of the technique used in "regular" precleaning.
- if (stop_point != NULL) {
+ // If unable to process the card then we encountered an unparsable
+ // part of the heap (e.g. a partially allocated object). Redirty
+ // and re-enqueue: if we put off the card until a GC pause, then the
+ // allocation will have completed.
+ if (!card_processed) {
+ assert(!_g1->is_gc_active(), "Unparsable heap during GC");
// The card might have gotten re-dirtied and re-enqueued while we
// worked. (In fact, it's pretty likely.)
if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
--- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp Tue Sep 27 20:55:13 2016 -0400
@@ -352,19 +352,10 @@
_prev_marked_bytes = marked_bytes;
}
-HeapWord*
-HeapRegion::
-oops_on_card_seq_iterate_careful(MemRegion mr,
- FilterOutOfRegionClosure* cl,
- bool filter_young,
- jbyte* card_ptr) {
- // Currently, we should only have to clean the card if filter_young
- // is true and vice versa.
- if (filter_young) {
- assert(card_ptr != NULL, "pre-condition");
- } else {
- assert(card_ptr == NULL, "pre-condition");
- }
+bool HeapRegion::oops_on_card_seq_iterate_careful(MemRegion mr,
+ FilterOutOfRegionClosure* cl,
+ jbyte* card_ptr) {
+ assert(card_ptr != NULL, "pre-condition");
G1CollectedHeap* g1h = G1CollectedHeap::heap();
// If we're within a stop-world GC, then we might look at a card in a
@@ -375,7 +366,9 @@
} else {
mr = mr.intersection(used_region());
}
- if (mr.is_empty()) return NULL;
+ if (mr.is_empty()) {
+ return true;
+ }
// Otherwise, find the obj that extends onto mr.start().
// The intersection of the incoming mr (for the card) and the
@@ -384,27 +377,21 @@
// G1CollectedHeap.cpp that allocates a new region sets the
// is_young tag on the region before allocating. Thus we
// safely know if this region is young.
- if (is_young() && filter_young) {
- return NULL;
+ if (is_young()) {
+ return true;
}
- assert(!is_young(), "check value of filter_young");
-
// We can only clean the card here, after we make the decision that
- // the card is not young. And we only clean the card if we have been
- // asked to (i.e., card_ptr != NULL).
- if (card_ptr != NULL) {
- *card_ptr = CardTableModRefBS::clean_card_val();
- // We must complete this write before we do any of the reads below.
- OrderAccess::storeload();
- }
+ // the card is not young.
+ *card_ptr = CardTableModRefBS::clean_card_val();
+ // We must complete this write before we do any of the reads below.
+ OrderAccess::storeload();
// Cache the boundaries of the memory region in some const locals
HeapWord* const start = mr.start();
HeapWord* const end = mr.end();
- // We used to use "block_start_careful" here. But we're actually happy
- // to update the BOT while we do this...
+ // Update BOT as needed while finding start of (potential) object.
HeapWord* cur = block_start(start);
assert(cur <= start, "Postcondition");
@@ -416,7 +403,9 @@
obj = oop(cur);
if (obj->klass_or_null() == NULL) {
// Ran into an unparseable point.
- return cur;
+ assert(!g1h->is_gc_active(),
+ "Unparsable heap during GC at " PTR_FORMAT, p2i(cur));
+ return false;
}
// Otherwise...
next = cur + block_size(cur);
@@ -433,7 +422,9 @@
assert((cur + block_size(cur)) > (HeapWord*)obj, "Loop invariant");
if (obj->klass_or_null() == NULL) {
// Ran into an unparseable point.
- return cur;
+ assert(!g1h->is_gc_active(),
+ "Unparsable heap during GC at " PTR_FORMAT, p2i(cur));
+ return false;
}
// Advance the current pointer. "obj" still points to the object to iterate.
@@ -452,7 +443,7 @@
}
} while (cur < end);
- return NULL;
+ return true;
}
// Code roots support
--- a/hotspot/src/share/vm/gc/g1/heapRegion.hpp Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.hpp Tue Sep 27 20:55:13 2016 -0400
@@ -653,16 +653,17 @@
}
}
- // filter_young: if true and the region is a young region then we
- // skip the iteration.
- // card_ptr: if not NULL, and we decide that the card is not young
- // and we iterate over it, we'll clean the card before we start the
- // iteration.
- HeapWord*
- oops_on_card_seq_iterate_careful(MemRegion mr,
- FilterOutOfRegionClosure* cl,
- bool filter_young,
- jbyte* card_ptr);
+ // Iterate over the card in the card designated by card_ptr,
+ // applying cl to all references in the region.
+ // mr: the memory region covered by the card.
+ // card_ptr: if we decide that the card is not young and we iterate
+ // over it, we'll clean the card before we start the iteration.
+ // Returns true if card was successfully processed, false if an
+ // unparsable part of the heap was encountered, which should only
+ // happen when invoked concurrently with the mutator.
+ bool oops_on_card_seq_iterate_careful(MemRegion mr,
+ FilterOutOfRegionClosure* cl,
+ jbyte* card_ptr);
size_t recorded_rs_length() const { return _recorded_rs_length; }
double predicted_elapsed_time_ms() const { return _predicted_elapsed_time_ms; }
--- a/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp Tue Sep 27 20:55:13 2016 -0400
@@ -482,8 +482,9 @@
HeapRegionClaimer::HeapRegionClaimer(uint n_workers) :
_n_workers(n_workers), _n_regions(G1CollectedHeap::heap()->_hrm._allocated_heapregions_length), _claims(NULL) {
assert(n_workers > 0, "Need at least one worker.");
- _claims = NEW_C_HEAP_ARRAY(uint, _n_regions, mtGC);
- memset(_claims, Unclaimed, sizeof(*_claims) * _n_regions);
+ uint* new_claims = NEW_C_HEAP_ARRAY(uint, _n_regions, mtGC);
+ memset(new_claims, Unclaimed, sizeof(*_claims) * _n_regions);
+ _claims = new_claims;
}
HeapRegionClaimer::~HeapRegionClaimer() {
--- a/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp Tue Sep 27 20:55:13 2016 -0400
@@ -259,9 +259,9 @@
// The HeapRegionClaimer is used during parallel iteration over heap regions,
// allowing workers to claim heap regions, gaining exclusive rights to these regions.
class HeapRegionClaimer : public StackObj {
- uint _n_workers;
- uint _n_regions;
- uint* _claims;
+ uint _n_workers;
+ uint _n_regions;
+ volatile uint* _claims;
static const uint Unclaimed = 0;
static const uint Claimed = 1;
@@ -285,4 +285,3 @@
bool claim_region(uint region_index);
};
#endif // SHARE_VM_GC_G1_HEAPREGIONMANAGER_HPP
-
--- a/hotspot/src/share/vm/oops/oop.hpp Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/src/share/vm/oops/oop.hpp Tue Sep 27 20:55:13 2016 -0400
@@ -83,6 +83,7 @@
inline Klass* klass() const;
inline Klass* klass_or_null() const volatile;
+ inline Klass* klass_or_null_acquire() const volatile;
inline Klass** klass_addr();
inline narrowKlass* compressed_klass_addr();
--- a/hotspot/src/share/vm/oops/oop.inline.hpp Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/src/share/vm/oops/oop.inline.hpp Tue Sep 27 20:55:13 2016 -0400
@@ -109,7 +109,6 @@
}
Klass* oopDesc::klass_or_null() const volatile {
- // can be NULL in CMS
if (UseCompressedClassPointers) {
return Klass::decode_klass(_metadata._compressed_klass);
} else {
@@ -117,6 +116,17 @@
}
}
+Klass* oopDesc::klass_or_null_acquire() const volatile {
+ if (UseCompressedClassPointers) {
+ // Workaround for non-const load_acquire parameter.
+ const volatile narrowKlass* addr = &_metadata._compressed_klass;
+ volatile narrowKlass* xaddr = const_cast<volatile narrowKlass*>(addr);
+ return Klass::decode_klass(OrderAccess::load_acquire(xaddr));
+ } else {
+ return (Klass*)OrderAccess::load_ptr_acquire(&_metadata._klass);
+ }
+}
+
Klass** oopDesc::klass_addr() {
// Only used internally and with CMS and will not work with
// UseCompressedOops
--- a/hotspot/src/share/vm/utilities/chunkedList.cpp Mon Sep 26 14:21:21 2016 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "utilities/chunkedList.hpp"
-#include "utilities/debug.hpp"
-
-/////////////// Unit tests ///////////////
-
-#ifndef PRODUCT
-
-template <typename T>
-class TestChunkedList {
- typedef ChunkedList<T, mtOther> ChunkedListT;
-
- public:
- static void testEmpty() {
- ChunkedListT buffer;
- assert(buffer.size() == 0, "assert");
- }
-
- static void testFull() {
- ChunkedListT buffer;
- for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) {
- buffer.push((T)i);
- }
- assert(buffer.size() == ChunkedListT::BufferSize, "assert");
- assert(buffer.is_full(), "assert");
- }
-
- static void testSize() {
- ChunkedListT buffer;
- for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) {
- assert(buffer.size() == i, "assert");
- buffer.push((T)i);
- assert(buffer.size() == i + 1, "assert");
- }
- }
-
- static void testClear() {
- ChunkedListT buffer;
-
- buffer.clear();
- assert(buffer.size() == 0, "assert");
-
- for (uintptr_t i = 0; i < ChunkedListT::BufferSize / 2; i++) {
- buffer.push((T)i);
- }
- buffer.clear();
- assert(buffer.size() == 0, "assert");
-
- for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) {
- buffer.push((T)i);
- }
- buffer.clear();
- assert(buffer.size() == 0, "assert");
- }
-
- static void testAt() {
- ChunkedListT buffer;
-
- for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) {
- buffer.push((T)i);
- assert(buffer.at(i) == (T)i, "assert");
- }
-
- for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) {
- assert(buffer.at(i) == (T)i, "assert");
- }
- }
-
- static void test() {
- testEmpty();
- testFull();
- testSize();
- testClear();
- testAt();
- }
-};
-
-class Metadata;
-
-void TestChunkedList_test() {
- TestChunkedList<Metadata*>::test();
- TestChunkedList<size_t>::test();
-}
-
-#endif
--- a/hotspot/src/share/vm/utilities/internalVMTests.cpp Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp Tue Sep 27 20:55:13 2016 -0400
@@ -60,7 +60,6 @@
run_unit_test(TestBitMap_test);
run_unit_test(TestResourcehash_test);
run_unit_test(ObjectMonitor_test);
- run_unit_test(TestChunkedList_test);
run_unit_test(Test_log_tag_combinations_limit);
run_unit_test(Test_logtarget);
run_unit_test(Test_logstream);
@@ -86,7 +85,6 @@
run_unit_test(TestBufferingOopClosure_test);
if (UseG1GC) {
run_unit_test(FreeRegionList_test);
- run_unit_test(IHOP_test);
}
run_unit_test(WorkerDataArray_test);
run_unit_test(ParallelCompact_test);
--- a/hotspot/test/jprt.config Mon Sep 26 14:21:21 2016 -0400
+++ b/hotspot/test/jprt.config Tue Sep 27 20:55:13 2016 -0400
@@ -86,12 +86,12 @@
fi
# Add basic solaris system paths
- path4sdk=/usr/ccs/bin:/usr/ccs/lib:/usr/bin:/bin:/usr/sfw/bin
+ path4sdk=/usr/bin
# Find GNU make
- make=/usr/sfw/bin/gmake
+ make=/usr/bin/gmake
if [ ! -f ${make} ] ; then
- make=/opt/sfw/bin/gmake
+ make=/usr/gnu/bin/make
if [ ! -f ${make} ] ; then
make=${slashjava}/devtools/${solaris_arch}/bin/gnumake
fi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/native/gc/g1/test_g1IHOPControl.cpp Tue Sep 27 20:55:13 2016 -0400
@@ -0,0 +1,149 @@
+/*
+ * 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 "precompiled.hpp"
+#include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "gc/g1/g1IHOPControl.hpp"
+#include "gc/g1/g1Predictions.hpp"
+#include "unittest.hpp"
+
+static void test_update(G1IHOPControl* ctrl, double alloc_time,
+ size_t alloc_amount, size_t young_size,
+ double mark_time) {
+ for (int i = 0; i < 100; i++) {
+ ctrl->update_allocation_info(alloc_time, alloc_amount, young_size);
+ ctrl->update_marking_length(mark_time);
+ }
+}
+
+// @requires UseG1GC
+TEST_VM(G1StaticIHOPControl, simple) {
+ // Test requires G1
+ if (!UseG1GC) {
+ return;
+ }
+
+ const size_t initial_ihop = 45;
+
+ G1StaticIHOPControl ctrl(initial_ihop);
+ ctrl.update_target_occupancy(100);
+
+ size_t threshold = ctrl.get_conc_mark_start_threshold();
+ EXPECT_EQ(initial_ihop, threshold);
+
+ ctrl.update_allocation_info(100.0, 100, 100);
+ threshold = ctrl.get_conc_mark_start_threshold();
+ EXPECT_EQ(initial_ihop, threshold);
+
+ ctrl.update_marking_length(1000.0);
+ threshold = ctrl.get_conc_mark_start_threshold();
+ EXPECT_EQ(initial_ihop, threshold);
+
+ // Whatever we pass, the IHOP value must stay the same.
+ test_update(&ctrl, 2, 10, 10, 3);
+ threshold = ctrl.get_conc_mark_start_threshold();
+
+ EXPECT_EQ(initial_ihop, threshold);
+
+ test_update(&ctrl, 12, 10, 10, 3);
+ threshold = ctrl.get_conc_mark_start_threshold();
+
+ EXPECT_EQ(initial_ihop, threshold);
+}
+
+// @requires UseG1GC
+TEST_VM(G1AdaptiveIHOPControl, simple) {
+ // Test requires G1
+ if (!UseG1GC) {
+ return;
+ }
+
+ const size_t initial_threshold = 45;
+ const size_t young_size = 10;
+ const size_t target_size = 100;
+
+ // The final IHOP value is always
+ // target_size - (young_size + alloc_amount/alloc_time * marking_time)
+
+ G1Predictions pred(0.95);
+ G1AdaptiveIHOPControl ctrl(initial_threshold, &pred, 0, 0);
+ ctrl.update_target_occupancy(target_size);
+
+ // First "load".
+ const size_t alloc_time1 = 2;
+ const size_t alloc_amount1 = 10;
+ const size_t marking_time1 = 2;
+ const size_t settled_ihop1 = target_size
+ - (young_size + alloc_amount1 / alloc_time1 * marking_time1);
+
+ size_t threshold;
+ threshold = ctrl.get_conc_mark_start_threshold();
+
+ EXPECT_EQ(initial_threshold, threshold);
+
+ for (size_t i = 0; i < G1AdaptiveIHOPNumInitialSamples - 1; i++) {
+ ctrl.update_allocation_info(alloc_time1, alloc_amount1, young_size);
+ ctrl.update_marking_length(marking_time1);
+ // Not enough data yet.
+ threshold = ctrl.get_conc_mark_start_threshold();
+
+ ASSERT_EQ(initial_threshold, threshold) << "on step " << i;
+ }
+
+ test_update(&ctrl, alloc_time1, alloc_amount1, young_size, marking_time1);
+
+ threshold = ctrl.get_conc_mark_start_threshold();
+
+ EXPECT_EQ(settled_ihop1, threshold);
+
+ // Second "load". A bit higher allocation rate.
+ const size_t alloc_time2 = 2;
+ const size_t alloc_amount2 = 30;
+ const size_t marking_time2 = 2;
+ const size_t settled_ihop2 = target_size
+ - (young_size + alloc_amount2 / alloc_time2 * marking_time2);
+
+ test_update(&ctrl, alloc_time2, alloc_amount2, young_size, marking_time2);
+
+ threshold = ctrl.get_conc_mark_start_threshold();
+
+ EXPECT_LT(threshold, settled_ihop1);
+
+ // Third "load". Very high (impossible) allocation rate.
+ const size_t alloc_time3 = 1;
+ const size_t alloc_amount3 = 50;
+ const size_t marking_time3 = 2;
+ const size_t settled_ihop3 = 0;
+
+ test_update(&ctrl, alloc_time3, alloc_amount3, young_size, marking_time3);
+ threshold = ctrl.get_conc_mark_start_threshold();
+
+ EXPECT_EQ(settled_ihop3, threshold);
+
+ // And back to some arbitrary value.
+ test_update(&ctrl, alloc_time2, alloc_amount2, young_size, marking_time2);
+
+ threshold = ctrl.get_conc_mark_start_threshold();
+
+ EXPECT_GT(threshold, settled_ihop3);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/native/utilities/test_chunkedList.cpp Tue Sep 27 20:55:13 2016 -0400
@@ -0,0 +1,130 @@
+/*
+ * 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
+ * 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 "precompiled.hpp"
+#include "unittest.hpp"
+#include "utilities/chunkedList.hpp"
+
+class Metadata;
+
+template <typename T>
+class TestChunkedList {
+ typedef ChunkedList<T, mtOther> ChunkedListT;
+
+ public:
+
+ static void testEmpty() {
+ ChunkedListT buffer;
+ ASSERT_EQ((size_t) 0, buffer.size());
+ }
+
+ static void testFull() {
+ ChunkedListT buffer;
+ for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) {
+ buffer.push((T) i);
+ }
+ ASSERT_EQ((size_t) ChunkedListT::BufferSize, buffer.size());
+ ASSERT_TRUE(buffer.is_full());
+ }
+
+ static void testSize() {
+ ChunkedListT buffer;
+ for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) {
+ ASSERT_EQ((size_t) i, buffer.size());
+ buffer.push((T) i);
+ ASSERT_EQ((size_t) (i + 1), buffer.size());
+ }
+ }
+
+ static void testClear() {
+ ChunkedListT buffer;
+
+ buffer.clear();
+ ASSERT_EQ((size_t) 0, buffer.size());
+
+ for (uintptr_t i = 0; i < ChunkedListT::BufferSize / 2; i++) {
+ buffer.push((T) i);
+ }
+ buffer.clear();
+ ASSERT_EQ((size_t) 0, buffer.size());
+
+ for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) {
+ buffer.push((T) i);
+ }
+ buffer.clear();
+ ASSERT_EQ((size_t) 0, buffer.size());
+ }
+
+ static void testAt() {
+ ChunkedListT buffer;
+
+ for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) {
+ buffer.push((T) i);
+ ASSERT_EQ((T) i, buffer.at(i));
+ }
+
+ for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) {
+ ASSERT_EQ((T) i, buffer.at(i));
+ }
+ }
+};
+
+TEST(ChunkedList, metadata_empty) {
+ TestChunkedList<Metadata*>::testEmpty();
+}
+
+TEST(ChunkedList, metadata_full) {
+ TestChunkedList<Metadata*>::testFull();
+}
+
+TEST(ChunkedList, metadata_size) {
+ TestChunkedList<Metadata*>::testSize();
+}
+
+TEST(ChunkedList, metadata_clear) {
+ TestChunkedList<Metadata*>::testSize();
+}
+
+TEST(ChunkedList, metadata_at) {
+ TestChunkedList<Metadata*>::testAt();
+}
+
+TEST(ChunkedList, size_t_empty) {
+ TestChunkedList<size_t>::testEmpty();
+}
+
+TEST(ChunkedList, size_t_full) {
+ TestChunkedList<size_t>::testFull();
+}
+
+TEST(ChunkedList, size_t_size) {
+ TestChunkedList<size_t>::testSize();
+}
+
+TEST(ChunkedList, size_t_clear) {
+ TestChunkedList<size_t>::testSize();
+}
+
+TEST(ChunkedList, size_t_at) {
+ TestChunkedList<size_t>::testAt();
+}