8195103: Refactor out card table from CardTableModRefBS to flatten the BarrierSet hierarchy
Reviewed-by: kbarrett, tschatzl
--- a/src/hotspot/share/gc/cms/cmsHeap.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/cms/cmsHeap.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -75,10 +75,6 @@
// supports. Caller does not hold the Heap_lock on entry.
void collect(GCCause::Cause cause);
- bool card_mark_must_follow_store() const {
- return true;
- }
-
void stop();
void safepoint_synchronize_begin();
void safepoint_synchronize_end();
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Wed Jan 10 22:48:27 2018 +0100
@@ -1573,7 +1573,6 @@
}
jint G1CollectedHeap::initialize() {
- CollectedHeap::pre_initialize();
os::enable_vtime();
// Necessary to satisfy locking discipline assertions.
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1272,36 +1272,8 @@
size_t max_tlab_size() const;
size_t unsafe_max_tlab_alloc(Thread* ignored) const;
- // Can a compiler initialize a new object without store barriers?
- // This permission only extends from the creation of a new object
- // via a TLAB up to the first subsequent safepoint. If such permission
- // is granted for this heap type, the compiler promises to call
- // defer_store_barrier() below on any slow path allocation of
- // a new object for which such initializing store barriers will
- // have been elided. G1, like CMS, allows this, but should be
- // ready to provide a compensating write barrier as necessary
- // if that storage came out of a non-young region. The efficiency
- // of this implementation depends crucially on being able to
- // answer very efficiently in constant time whether a piece of
- // storage in the heap comes from a young region or not.
- // See ReduceInitialCardMarks.
- virtual bool can_elide_tlab_store_barriers() const {
- return true;
- }
-
- virtual bool card_mark_must_follow_store() const {
- return true;
- }
-
inline bool is_in_young(const oop obj);
- // We don't need barriers for initializing stores to objects
- // in the young gen: for the SATB pre-barrier, there is no
- // pre-value that needs to be remembered; for the remembered-set
- // update logging post-barrier, we don't maintain remembered set
- // information for young gen objects.
- virtual inline bool can_elide_initializing_store_barrier(oop new_obj);
-
// Returns "true" iff the given word_size is "very large".
static bool is_humongous(size_t word_size) {
// Note this has to be strictly greater-than as the TLABs
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -241,15 +241,6 @@
return heap_region_containing(obj)->is_young();
}
-// We don't need barriers for initializing stores to objects
-// in the young gen: for the SATB pre-barrier, there is no
-// pre-value that needs to be remembered; for the remembered-set
-// update logging post-barrier, we don't maintain remembered set
-// information for young gen objects.
-inline bool G1CollectedHeap::can_elide_initializing_store_barrier(oop new_obj) {
- return is_in_young(new_obj);
-}
-
inline bool G1CollectedHeap::is_obj_dead(const oop obj) const {
if (obj == NULL) {
return false;
--- a/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.cpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.cpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -131,6 +131,7 @@
}
void G1SATBCardTableLoggingModRefBS::initialize(G1RegionToSpaceMapper* mapper) {
+ initialize_deferred_card_mark_barriers();
mapper->set_mapping_changed_listener(&_listener);
_byte_map_size = mapper->reserved().byte_size();
@@ -213,3 +214,14 @@
}
}
}
+
+bool G1SATBCardTableModRefBS::is_in_young(oop obj) const {
+ volatile jbyte* p = byte_for((void*)obj);
+ return *p == g1_young_card_val();
+}
+
+void G1SATBCardTableLoggingModRefBS::flush_deferred_barriers(JavaThread* thread) {
+ CardTableModRefBS::flush_deferred_barriers(thread);
+ thread->satb_mark_queue().flush();
+ thread->dirty_card_queue().flush();
+}
--- a/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -92,6 +92,8 @@
jbyte val = _byte_map[card_index];
return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val();
}
+
+ virtual bool is_in_young(oop obj) const;
};
template<>
@@ -145,13 +147,19 @@
// above no longer applies.
void invalidate(MemRegion mr);
- void write_region_work(MemRegion mr) { invalidate(mr); }
+ void write_region(MemRegion mr) { invalidate(mr); }
void write_ref_array_work(MemRegion mr) { invalidate(mr); }
template <DecoratorSet decorators, typename T>
void write_ref_field_post(T* field, oop new_val);
void write_ref_field_post_slow(volatile jbyte* byte);
+ virtual void flush_deferred_barriers(JavaThread* thread);
+
+ virtual bool card_mark_must_follow_store() const {
+ return true;
+ }
+
// Callbacks for runtime accesses.
template <DecoratorSet decorators, typename BarrierSetT = G1SATBCardTableLoggingModRefBS>
class AccessBarrier: public ModRefBarrierSet::AccessBarrier<decorators, BarrierSetT> {
--- a/src/hotspot/share/gc/parallel/cardTableExtension.cpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/parallel/cardTableExtension.cpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -26,7 +26,7 @@
#include "gc/parallel/cardTableExtension.hpp"
#include "gc/parallel/gcTaskManager.hpp"
#include "gc/parallel/objectStartArray.inline.hpp"
-#include "gc/parallel/parallelScavengeHeap.hpp"
+#include "gc/parallel/parallelScavengeHeap.inline.hpp"
#include "gc/parallel/psPromotionManager.inline.hpp"
#include "gc/parallel/psScavenge.hpp"
#include "gc/parallel/psTasks.hpp"
@@ -677,3 +677,7 @@
}
return min_start;
}
+
+bool CardTableExtension::is_in_young(oop obj) const {
+ return ParallelScavengeHeap::heap()->is_in_young(obj);
+}
--- a/src/hotspot/share/gc/parallel/cardTableExtension.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/parallel/cardTableExtension.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -108,6 +108,13 @@
}
#endif // ASSERT
+
+ // ReduceInitialCardMarks support
+ virtual bool is_in_young(oop obj) const;
+
+ virtual bool card_mark_must_follow_store() const {
+ return false;
+ }
};
template<>
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -57,8 +57,6 @@
GCTaskManager* ParallelScavengeHeap::_gc_task_manager = NULL;
jint ParallelScavengeHeap::initialize() {
- CollectedHeap::pre_initialize();
-
const size_t heap_size = _collector_policy->max_heap_byte_size();
ReservedSpace heap_rs = Universe::reserve_heap(heap_size, _collector_policy->heap_alignment());
@@ -490,13 +488,6 @@
CollectedHeap::resize_all_tlabs();
}
-bool ParallelScavengeHeap::can_elide_initializing_store_barrier(oop new_obj) {
- // We don't need barriers for stores to objects in the
- // young gen and, a fortiori, for initializing stores to
- // objects therein.
- return is_in_young(new_obj);
-}
-
// This method is used by System.gc() and JVMTI.
void ParallelScavengeHeap::collect(GCCause::Cause cause) {
assert(!Heap_lock->owned_by_self(),
@@ -719,4 +710,3 @@
memory_pools.append(_old_pool);
return memory_pools;
}
-
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -205,21 +205,6 @@
size_t tlab_used(Thread* thr) const;
size_t unsafe_max_tlab_alloc(Thread* thr) const;
- // Can a compiler initialize a new object without store barriers?
- // This permission only extends from the creation of a new object
- // via a TLAB up to the first subsequent safepoint.
- virtual bool can_elide_tlab_store_barriers() const {
- return true;
- }
-
- virtual bool card_mark_must_follow_store() const {
- return false;
- }
-
- // Return true if we don't we need a store barrier for
- // initializing stores to an object at this address.
- virtual bool can_elide_initializing_store_barrier(oop new_obj);
-
void object_iterate(ObjectClosure* cl);
void safe_object_iterate(ObjectClosure* cl) { object_iterate(cl); }
--- a/src/hotspot/share/gc/serial/serialHeap.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/serial/serialHeap.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -61,10 +61,6 @@
virtual bool is_in_closed_subset(const void* p) const {
return is_in(p);
}
-
- virtual bool card_mark_must_follow_store() const {
- return false;
- }
};
#endif // SHARE_VM_GC_CMS_CMSHEAP_HPP
--- a/src/hotspot/share/gc/shared/barrierSet.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/shared/barrierSet.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -32,6 +32,8 @@
#include "oops/oopsHierarchy.hpp"
#include "utilities/fakeRttiSupport.hpp"
+class JavaThread;
+
// This class provides the interface between a barrier implementation and
// the rest of the system.
@@ -107,19 +109,19 @@
static void static_write_ref_array_pre(HeapWord* start, size_t count);
static void static_write_ref_array_post(HeapWord* start, size_t count);
+ // Support for optimizing compilers to call the barrier set on slow path allocations
+ // that did not enter a TLAB. Used for e.g. ReduceInitialCardMarks.
+ // The allocation is safe to use iff it returns true. If not, the slow-path allocation
+ // is redone until it succeeds. This can e.g. prevent allocations from the slow path
+ // to be in old.
+ virtual void on_slowpath_allocation_exit(JavaThread* thread, oop new_obj) {}
+ virtual void flush_deferred_barriers(JavaThread* thread) {}
+ virtual void make_parsable(JavaThread* thread) {}
+
protected:
virtual void write_ref_array_work(MemRegion mr) = 0;
public:
- // (For efficiency reasons, this operation is specialized for certain
- // barrier types. Semantically, it should be thought of as a call to the
- // virtual "_work" function below, which must implement the barrier.)
- void write_region(MemRegion mr);
-
-protected:
- virtual void write_region_work(MemRegion mr) = 0;
-
-public:
// Inform the BarrierSet that the the covered heap region that starts
// with "base" has been changed to have the given size (possibly from 0,
// for initialization.)
--- a/src/hotspot/share/gc/shared/barrierSet.inline.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/shared/barrierSet.inline.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -52,8 +52,4 @@
write_ref_array_work(MemRegion(aligned_start, aligned_end));
}
-inline void BarrierSet::write_region(MemRegion mr) {
- write_region_work(mr);
-}
-
#endif // SHARE_VM_GC_SHARED_BARRIERSET_INLINE_HPP
--- a/src/hotspot/share/gc/shared/cardTableModRefBS.cpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/shared/cardTableModRefBS.cpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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,6 +30,7 @@
#include "logging/log.hpp"
#include "memory/virtualspace.hpp"
#include "oops/oop.inline.hpp"
+#include "runtime/thread.hpp"
#include "services/memTracker.hpp"
#include "utilities/align.hpp"
#include "utilities/macros.hpp"
@@ -61,7 +62,8 @@
_committed(NULL),
_cur_covered_regions(0),
_byte_map(NULL),
- byte_map_base(NULL)
+ byte_map_base(NULL),
+ _defer_initial_card_mark(false)
{
assert((uintptr_t(_whole_heap.start()) & (card_size - 1)) == 0, "heap must start at card boundary");
assert((uintptr_t(_whole_heap.end()) & (card_size - 1)) == 0, "heap must end at card boundary");
@@ -75,6 +77,7 @@
}
void CardTableModRefBS::initialize() {
+ initialize_deferred_card_mark_barriers();
_guard_index = cards_required(_whole_heap.word_size()) - 1;
_last_valid_index = _guard_index - 1;
@@ -521,3 +524,112 @@
st->print_cr("Card table byte_map: [" INTPTR_FORMAT "," INTPTR_FORMAT "] byte_map_base: " INTPTR_FORMAT,
p2i(_byte_map), p2i(_byte_map + _byte_map_size), p2i(byte_map_base));
}
+
+// Helper for ReduceInitialCardMarks. For performance,
+// compiled code may elide card-marks for initializing stores
+// to a newly allocated object along the fast-path. We
+// compensate for such elided card-marks as follows:
+// (a) Generational, non-concurrent collectors, such as
+// GenCollectedHeap(ParNew,DefNew,Tenured) and
+// ParallelScavengeHeap(ParallelGC, ParallelOldGC)
+// need the card-mark if and only if the region is
+// in the old gen, and do not care if the card-mark
+// succeeds or precedes the initializing stores themselves,
+// so long as the card-mark is completed before the next
+// scavenge. For all these cases, we can do a card mark
+// at the point at which we do a slow path allocation
+// in the old gen, i.e. in this call.
+// (b) GenCollectedHeap(ConcurrentMarkSweepGeneration) requires
+// in addition that the card-mark for an old gen allocated
+// object strictly follow any associated initializing stores.
+// In these cases, the memRegion remembered below is
+// used to card-mark the entire region either just before the next
+// slow-path allocation by this thread or just before the next scavenge or
+// CMS-associated safepoint, whichever of these events happens first.
+// (The implicit assumption is that the object has been fully
+// initialized by this point, a fact that we assert when doing the
+// card-mark.)
+// (c) G1CollectedHeap(G1) uses two kinds of write barriers. When a
+// G1 concurrent marking is in progress an SATB (pre-write-)barrier
+// is used to remember the pre-value of any store. Initializing
+// stores will not need this barrier, so we need not worry about
+// compensating for the missing pre-barrier here. Turning now
+// to the post-barrier, we note that G1 needs a RS update barrier
+// which simply enqueues a (sequence of) dirty cards which may
+// optionally be refined by the concurrent update threads. Note
+// that this barrier need only be applied to a non-young write,
+// but, like in CMS, because of the presence of concurrent refinement
+// (much like CMS' precleaning), must strictly follow the oop-store.
+// Thus, using the same protocol for maintaining the intended
+// invariants turns out, serendepitously, to be the same for both
+// G1 and CMS.
+//
+// For any future collector, this code should be reexamined with
+// that specific collector in mind, and the documentation above suitably
+// extended and updated.
+void CardTableModRefBS::on_slowpath_allocation_exit(JavaThread* thread, oop new_obj) {
+ if (!ReduceInitialCardMarks) {
+ return;
+ }
+ // If a previous card-mark was deferred, flush it now.
+ flush_deferred_card_mark_barrier(thread);
+ if (new_obj->is_typeArray() || is_in_young(new_obj)) {
+ // Arrays of non-references don't need a post-barrier.
+ // The deferred_card_mark region should be empty
+ // following the flush above.
+ assert(thread->deferred_card_mark().is_empty(), "Error");
+ } else {
+ MemRegion mr((HeapWord*)new_obj, new_obj->size());
+ assert(!mr.is_empty(), "Error");
+ if (_defer_initial_card_mark) {
+ // Defer the card mark
+ thread->set_deferred_card_mark(mr);
+ } else {
+ // Do the card mark
+ write_region(mr);
+ }
+ }
+}
+
+void CardTableModRefBS::initialize_deferred_card_mark_barriers() {
+ // Used for ReduceInitialCardMarks (when COMPILER2 or JVMCI is used);
+ // otherwise remains unused.
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ _defer_initial_card_mark = is_server_compilation_mode_vm() && ReduceInitialCardMarks && can_elide_tlab_store_barriers()
+ && (DeferInitialCardMark || card_mark_must_follow_store());
+#else
+ assert(_defer_initial_card_mark == false, "Who would set it?");
+#endif
+}
+
+void CardTableModRefBS::flush_deferred_card_mark_barrier(JavaThread* thread) {
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ MemRegion deferred = thread->deferred_card_mark();
+ if (!deferred.is_empty()) {
+ assert(_defer_initial_card_mark, "Otherwise should be empty");
+ {
+ // Verify that the storage points to a parsable object in heap
+ DEBUG_ONLY(oop old_obj = oop(deferred.start());)
+ assert(!is_in_young(old_obj),
+ "Else should have been filtered in on_slowpath_allocation_exit()");
+ assert(oopDesc::is_oop(old_obj, true), "Not an oop");
+ assert(deferred.word_size() == (size_t)(old_obj->size()),
+ "Mismatch: multiple objects?");
+ }
+ write_region(deferred);
+ // "Clear" the deferred_card_mark field
+ thread->set_deferred_card_mark(MemRegion());
+ }
+ assert(thread->deferred_card_mark().is_empty(), "invariant");
+#else
+ assert(!_defer_initial_card_mark, "Should be false");
+ assert(thread->deferred_card_mark().is_empty(), "Should be empty");
+#endif
+}
+
+void CardTableModRefBS::flush_deferred_barriers(JavaThread* thread) {
+ // The deferred store barriers must all have been flushed to the
+ // card-table (or other remembered set structure) before GC starts
+ // processing the card-table (or other remembered set).
+ flush_deferred_card_mark_barrier(thread);
+}
--- a/src/hotspot/share/gc/shared/cardTableModRefBS.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/shared/cardTableModRefBS.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -58,6 +58,10 @@
CT_MR_BS_last_reserved = 16
};
+ // Used in support of ReduceInitialCardMarks; only consulted if COMPILER2
+ // or INCLUDE_JVMCI is being used
+ bool _defer_initial_card_mark;
+
// a word's worth (row) of clean card values
static const intptr_t clean_card_row = (intptr_t)(-1);
@@ -180,8 +184,8 @@
CardTableModRefBS(MemRegion whole_heap, const BarrierSet::FakeRtti& fake_rtti);
~CardTableModRefBS();
- protected:
- void write_region_work(MemRegion mr) {
+ public:
+ void write_region(MemRegion mr) {
dirty_MemRegion(mr);
}
@@ -314,6 +318,49 @@
void verify_not_dirty_region(MemRegion mr) PRODUCT_RETURN;
void verify_dirty_region(MemRegion mr) PRODUCT_RETURN;
+ // ReduceInitialCardMarks
+ void initialize_deferred_card_mark_barriers();
+
+ // If the CollectedHeap was asked to defer a store barrier above,
+ // this informs it to flush such a deferred store barrier to the
+ // remembered set.
+ void flush_deferred_card_mark_barrier(JavaThread* thread);
+
+ // Can a compiler initialize a new object without store barriers?
+ // This permission only extends from the creation of a new object
+ // via a TLAB up to the first subsequent safepoint. If such permission
+ // is granted for this heap type, the compiler promises to call
+ // defer_store_barrier() below on any slow path allocation of
+ // a new object for which such initializing store barriers will
+ // have been elided. G1, like CMS, allows this, but should be
+ // ready to provide a compensating write barrier as necessary
+ // if that storage came out of a non-young region. The efficiency
+ // of this implementation depends crucially on being able to
+ // answer very efficiently in constant time whether a piece of
+ // storage in the heap comes from a young region or not.
+ // See ReduceInitialCardMarks.
+ virtual bool can_elide_tlab_store_barriers() const {
+ return true;
+ }
+
+ // If a compiler is eliding store barriers for TLAB-allocated objects,
+ // we will be informed of a slow-path allocation by a call
+ // to on_slowpath_allocation_exit() below. Such a call precedes the
+ // initialization of the object itself, and no post-store-barriers will
+ // be issued. Some heap types require that the barrier strictly follows
+ // the initializing stores. (This is currently implemented by deferring the
+ // barrier until the next slow-path allocation or gc-related safepoint.)
+ // This interface answers whether a particular barrier type needs the card
+ // mark to be thus strictly sequenced after the stores.
+ virtual bool card_mark_must_follow_store() const = 0;
+
+ virtual bool is_in_young(oop obj) const = 0;
+
+ virtual void on_slowpath_allocation_exit(JavaThread* thread, oop new_obj);
+ virtual void flush_deferred_barriers(JavaThread* thread);
+
+ virtual void make_parsable(JavaThread* thread) { flush_deferred_card_mark_barrier(thread); }
+
template <DecoratorSet decorators, typename BarrierSetT = CardTableModRefBS>
class AccessBarrier: public ModRefBarrierSet::AccessBarrier<decorators, BarrierSetT> {};
};
--- a/src/hotspot/share/gc/shared/cardTableModRefBSForCTRS.cpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/shared/cardTableModRefBSForCTRS.cpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -121,3 +121,6 @@
}
}
+bool CardTableModRefBSForCTRS::is_in_young(oop obj) const {
+ return GenCollectedHeap::heap()->is_in_young(obj);
+}
--- a/src/hotspot/share/gc/shared/cardTableModRefBSForCTRS.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/shared/cardTableModRefBSForCTRS.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -43,6 +43,12 @@
void set_CTRS(CardTableRS* rs) { _rs = rs; }
+ virtual bool card_mark_must_follow_store() const {
+ return UseConcMarkSweepGC;
+ }
+
+ virtual bool is_in_young(oop obj) const;
+
private:
CardTableRS* _rs;
--- a/src/hotspot/share/gc/shared/collectedHeap.cpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/shared/collectedHeap.cpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -177,8 +177,7 @@
_total_collections(0),
_total_full_collections(0),
_gc_cause(GCCause::_no_gc),
- _gc_lastcause(GCCause::_no_gc),
- _defer_initial_card_mark(false) // strengthened by subclass in pre_initialize() below.
+ _gc_lastcause(GCCause::_no_gc)
{
const size_t max_len = size_t(arrayOopDesc::max_array_length(T_INT));
const size_t elements_per_word = HeapWordSize / sizeof(jint);
@@ -239,17 +238,6 @@
BarrierSet::set_bs(barrier_set);
}
-void CollectedHeap::pre_initialize() {
- // Used for ReduceInitialCardMarks (when COMPILER2 is used);
- // otherwise remains unused.
-#if COMPILER2_OR_JVMCI
- _defer_initial_card_mark = is_server_compilation_mode_vm() && ReduceInitialCardMarks && can_elide_tlab_store_barriers()
- && (DeferInitialCardMark || card_mark_must_follow_store());
-#else
- assert(_defer_initial_card_mark == false, "Who would set it?");
-#endif
-}
-
#ifndef PRODUCT
void CollectedHeap::check_for_bad_heap_word_value(HeapWord* addr, size_t size) {
if (CheckMemoryInitialization && ZapUnusedHeapArea) {
@@ -333,28 +321,6 @@
return obj;
}
-void CollectedHeap::flush_deferred_store_barrier(JavaThread* thread) {
- MemRegion deferred = thread->deferred_card_mark();
- if (!deferred.is_empty()) {
- assert(_defer_initial_card_mark, "Otherwise should be empty");
- {
- // Verify that the storage points to a parsable object in heap
- DEBUG_ONLY(oop old_obj = oop(deferred.start());)
- assert(is_in(old_obj), "Not in allocated heap");
- assert(!can_elide_initializing_store_barrier(old_obj),
- "Else should have been filtered in new_store_pre_barrier()");
- assert(oopDesc::is_oop(old_obj, true), "Not an oop");
- assert(deferred.word_size() == (size_t)(old_obj->size()),
- "Mismatch: multiple objects?");
- }
- BarrierSet* bs = barrier_set();
- bs->write_region(deferred);
- // "Clear" the deferred_card_mark field
- thread->set_deferred_card_mark(MemRegion());
- }
- assert(thread->deferred_card_mark().is_empty(), "invariant");
-}
-
size_t CollectedHeap::max_tlab_size() const {
// TLABs can't be bigger than we can fill with a int[Integer.MAX_VALUE].
// This restriction could be removed by enabling filling with multiple arrays.
@@ -370,72 +336,6 @@
return align_down(max_int_size, MinObjAlignment);
}
-// Helper for ReduceInitialCardMarks. For performance,
-// compiled code may elide card-marks for initializing stores
-// to a newly allocated object along the fast-path. We
-// compensate for such elided card-marks as follows:
-// (a) Generational, non-concurrent collectors, such as
-// GenCollectedHeap(ParNew,DefNew,Tenured) and
-// ParallelScavengeHeap(ParallelGC, ParallelOldGC)
-// need the card-mark if and only if the region is
-// in the old gen, and do not care if the card-mark
-// succeeds or precedes the initializing stores themselves,
-// so long as the card-mark is completed before the next
-// scavenge. For all these cases, we can do a card mark
-// at the point at which we do a slow path allocation
-// in the old gen, i.e. in this call.
-// (b) GenCollectedHeap(ConcurrentMarkSweepGeneration) requires
-// in addition that the card-mark for an old gen allocated
-// object strictly follow any associated initializing stores.
-// In these cases, the memRegion remembered below is
-// used to card-mark the entire region either just before the next
-// slow-path allocation by this thread or just before the next scavenge or
-// CMS-associated safepoint, whichever of these events happens first.
-// (The implicit assumption is that the object has been fully
-// initialized by this point, a fact that we assert when doing the
-// card-mark.)
-// (c) G1CollectedHeap(G1) uses two kinds of write barriers. When a
-// G1 concurrent marking is in progress an SATB (pre-write-)barrier
-// is used to remember the pre-value of any store. Initializing
-// stores will not need this barrier, so we need not worry about
-// compensating for the missing pre-barrier here. Turning now
-// to the post-barrier, we note that G1 needs a RS update barrier
-// which simply enqueues a (sequence of) dirty cards which may
-// optionally be refined by the concurrent update threads. Note
-// that this barrier need only be applied to a non-young write,
-// but, like in CMS, because of the presence of concurrent refinement
-// (much like CMS' precleaning), must strictly follow the oop-store.
-// Thus, using the same protocol for maintaining the intended
-// invariants turns out, serendepitously, to be the same for both
-// G1 and CMS.
-//
-// For any future collector, this code should be reexamined with
-// that specific collector in mind, and the documentation above suitably
-// extended and updated.
-oop CollectedHeap::new_store_pre_barrier(JavaThread* thread, oop new_obj) {
- // If a previous card-mark was deferred, flush it now.
- flush_deferred_store_barrier(thread);
- if (can_elide_initializing_store_barrier(new_obj) ||
- new_obj->is_typeArray()) {
- // Arrays of non-references don't need a pre-barrier.
- // The deferred_card_mark region should be empty
- // following the flush above.
- assert(thread->deferred_card_mark().is_empty(), "Error");
- } else {
- MemRegion mr((HeapWord*)new_obj, new_obj->size());
- assert(!mr.is_empty(), "Error");
- if (_defer_initial_card_mark) {
- // Defer the card mark
- thread->set_deferred_card_mark(mr);
- } else {
- // Do the card mark
- BarrierSet* bs = barrier_set();
- bs->write_region(mr);
- }
- }
- return new_obj;
-}
-
size_t CollectedHeap::filler_array_hdr_size() {
return align_object_offset(arrayOopDesc::header_size(T_INT)); // align to Long
}
@@ -538,24 +438,16 @@
" otherwise concurrent mutator activity may make heap "
" unparsable again");
const bool use_tlab = UseTLAB;
- const bool deferred = _defer_initial_card_mark;
// The main thread starts allocating via a TLAB even before it
// has added itself to the threads list at vm boot-up.
JavaThreadIteratorWithHandle jtiwh;
assert(!use_tlab || jtiwh.length() > 0,
"Attempt to fill tlabs before main thread has been added"
" to threads list is doomed to failure!");
+ BarrierSet *bs = barrier_set();
for (; JavaThread *thread = jtiwh.next(); ) {
if (use_tlab) thread->tlab().make_parsable(retire_tlabs);
-#if COMPILER2_OR_JVMCI
- // The deferred store barriers must all have been flushed to the
- // card-table (or other remembered set structure) before GC starts
- // processing the card-table (or other remembered set).
- if (deferred) flush_deferred_store_barrier(thread);
-#else
- assert(!deferred, "Should be false");
- assert(thread->deferred_card_mark().is_empty(), "Should be empty");
-#endif
+ bs->make_parsable(thread);
}
}
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -101,10 +101,6 @@
GCHeapLog* _gc_heap_log;
- // Used in support of ReduceInitialCardMarks; only consulted if COMPILER2
- // or INCLUDE_JVMCI is being used
- bool _defer_initial_card_mark;
-
MemRegion _reserved;
protected:
@@ -129,13 +125,6 @@
// Constructor
CollectedHeap();
- // Do common initializations that must follow instance construction,
- // for example, those needing virtual calls.
- // This code could perhaps be moved into initialize() but would
- // be slightly more awkward because we want the latter to be a
- // pure virtual.
- void pre_initialize();
-
// Create a new tlab. All TLAB allocations must go through this.
virtual HeapWord* allocate_new_tlab(size_t size);
@@ -408,45 +397,6 @@
return 0;
}
- // Can a compiler initialize a new object without store barriers?
- // This permission only extends from the creation of a new object
- // via a TLAB up to the first subsequent safepoint. If such permission
- // is granted for this heap type, the compiler promises to call
- // defer_store_barrier() below on any slow path allocation of
- // a new object for which such initializing store barriers will
- // have been elided.
- virtual bool can_elide_tlab_store_barriers() const = 0;
-
- // If a compiler is eliding store barriers for TLAB-allocated objects,
- // there is probably a corresponding slow path which can produce
- // an object allocated anywhere. The compiler's runtime support
- // promises to call this function on such a slow-path-allocated
- // object before performing initializations that have elided
- // store barriers. Returns new_obj, or maybe a safer copy thereof.
- virtual oop new_store_pre_barrier(JavaThread* thread, oop new_obj);
-
- // Answers whether an initializing store to a new object currently
- // allocated at the given address doesn't need a store
- // barrier. Returns "true" if it doesn't need an initializing
- // store barrier; answers "false" if it does.
- virtual bool can_elide_initializing_store_barrier(oop new_obj) = 0;
-
- // If a compiler is eliding store barriers for TLAB-allocated objects,
- // we will be informed of a slow-path allocation by a call
- // to new_store_pre_barrier() above. Such a call precedes the
- // initialization of the object itself, and no post-store-barriers will
- // be issued. Some heap types require that the barrier strictly follows
- // the initializing stores. (This is currently implemented by deferring the
- // barrier until the next slow-path allocation or gc-related safepoint.)
- // This interface answers whether a particular heap type needs the card
- // mark to be thus strictly sequenced after the stores.
- virtual bool card_mark_must_follow_store() const = 0;
-
- // If the CollectedHeap was asked to defer a store barrier above,
- // this informs it to flush such a deferred store barrier to the
- // remembered set.
- virtual void flush_deferred_store_barrier(JavaThread* thread);
-
// Perform a collection of the heap; intended for use in implementing
// "System.gc". This probably implies as full a collection as the
// "CollectedHeap" supports.
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -71,8 +71,6 @@
}
jint GenCollectedHeap::initialize() {
- CollectedHeap::pre_initialize();
-
// While there are no constraints in the GC code that HeapWordSize
// be any particular value, there are multiple other areas in the
// system which believe this to be true (e.g. oop->object_size in some
--- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -270,22 +270,6 @@
virtual size_t unsafe_max_tlab_alloc(Thread* thr) const;
virtual HeapWord* allocate_new_tlab(size_t size);
- // Can a compiler initialize a new object without store barriers?
- // This permission only extends from the creation of a new object
- // via a TLAB up to the first subsequent safepoint.
- virtual bool can_elide_tlab_store_barriers() const {
- return true;
- }
-
- // We don't need barriers for stores to objects in the
- // young gen and, a fortiori, for initializing stores to
- // objects therein. This applies to DefNew+Tenured and ParNew+CMS
- // only and may need to be re-examined in case other
- // kinds of collectors are implemented in the future.
- virtual bool can_elide_initializing_store_barrier(oop new_obj) {
- return is_in_young(new_obj);
- }
-
// The "requestor" generation is performing some garbage collection
// action for which it would be useful to have scratch space. The
// requestor promises to allocate no more than "max_alloc_words" in any
--- a/src/hotspot/share/gc/shared/modRefBarrierSet.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/gc/shared/modRefBarrierSet.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -45,6 +45,7 @@
// Causes all refs in "mr" to be assumed to be modified.
virtual void invalidate(MemRegion mr) = 0;
+ virtual void write_region(MemRegion mr) = 0;
// The caller guarantees that "mr" contains no references. (Perhaps it's
// objects have been moved elsewhere.)
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp Wed Jan 10 22:48:27 2018 +0100
@@ -116,10 +116,7 @@
oop obj = ik->allocate_instance(CHECK);
thread->set_vm_result(obj);
JRT_BLOCK_END;
-
- if (ReduceInitialCardMarks) {
- new_store_pre_barrier(thread);
- }
+ SharedRuntime::on_slowpath_allocation_exit(thread);
JRT_END
JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array(JavaThread* thread, Klass* array_klass, jint length))
@@ -151,29 +148,9 @@
}
}
JRT_BLOCK_END;
-
- if (ReduceInitialCardMarks) {
- new_store_pre_barrier(thread);
- }
+ SharedRuntime::on_slowpath_allocation_exit(thread);
JRT_END
-void JVMCIRuntime::new_store_pre_barrier(JavaThread* thread) {
- // After any safepoint, just before going back to compiled code,
- // we inform the GC that we will be doing initializing writes to
- // this object in the future without emitting card-marks, so
- // GC may take any compensating steps.
- // NOTE: Keep this code consistent with GraphKit::store_barrier.
-
- oop new_obj = thread->vm_result();
- if (new_obj == NULL) return;
-
- assert(Universe::heap()->can_elide_tlab_store_barriers(),
- "compiler must check this first");
- // GC may decide to give back a safer copy of new_obj.
- new_obj = Universe::heap()->new_store_pre_barrier(thread, new_obj);
- thread->set_vm_result(new_obj);
-}
-
JRT_ENTRY(void, JVMCIRuntime::new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims))
assert(klass->is_klass(), "not a class");
assert(rank >= 1, "rank must be nonzero");
--- a/src/hotspot/share/jvmci/jvmciRuntime.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, 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,7 +154,6 @@
static void write_barrier_pre(JavaThread* thread, oopDesc* obj);
static void write_barrier_post(JavaThread* thread, void* card);
static jboolean validate_object(JavaThread* thread, oopDesc* parent, oopDesc* child);
- static void new_store_pre_barrier(JavaThread* thread);
// used to throw exceptions from compiled JVMCI code
static void throw_and_post_jvmti_exception(JavaThread* thread, const char* exception, const char* message);
--- a/src/hotspot/share/opto/graphKit.cpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/opto/graphKit.cpp Wed Jan 10 22:48:27 2018 +0100
@@ -3861,7 +3861,7 @@
if (use_ReduceInitialCardMarks()
&& obj == just_allocated_object(control())) {
// We can skip marks on a freshly-allocated object in Eden.
- // Keep this code in sync with new_store_pre_barrier() in runtime.cpp.
+ // Keep this code in sync with new_deferred_store_barrier() in runtime.cpp.
// That routine informs GC to take appropriate compensating steps,
// upon a slow-path allocation, so as to make this card-mark
// elision safe.
@@ -4159,7 +4159,7 @@
* as part of the allocation in the case the allocated object is not located
* in the nursery, this would happen for humongous objects. This is similar to
* how CMS is required to handle this case, see the comments for the method
- * CollectedHeap::new_store_pre_barrier and OptoRuntime::new_store_pre_barrier.
+ * CardTableModRefBS::on_allocation_slowpath_exit and OptoRuntime::new_deferred_store_barrier.
* A deferred card mark is required for these objects and handled in the above
* mentioned methods.
*
@@ -4249,7 +4249,7 @@
if (use_ReduceInitialCardMarks() && obj == just_allocated_object(control())) {
// We can skip marks on a freshly-allocated object in Eden.
- // Keep this code in sync with new_store_pre_barrier() in runtime.cpp.
+ // Keep this code in sync with new_deferred_store_barrier() in runtime.cpp.
// That routine informs GC to take appropriate compensating steps,
// upon a slow-path allocation, so as to make this card-mark
// elision safe.
--- a/src/hotspot/share/opto/graphKit.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/opto/graphKit.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -755,8 +755,10 @@
Node* just_allocated_object(Node* current_control);
static bool use_ReduceInitialCardMarks() {
- return (ReduceInitialCardMarks
- && Universe::heap()->can_elide_tlab_store_barriers());
+ BarrierSet *bs = Universe::heap()->barrier_set();
+ return bs->is_a(BarrierSet::CardTableModRef)
+ && barrier_set_cast<CardTableModRefBS>(bs)->can_elide_tlab_store_barriers()
+ && ReduceInitialCardMarks;
}
// Sync Ideal and Graph kits.
--- a/src/hotspot/share/opto/runtime.cpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/opto/runtime.cpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, 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
@@ -194,23 +194,6 @@
// We failed the fast-path allocation. Now we need to do a scavenge or GC
// and try allocation again.
-void OptoRuntime::new_store_pre_barrier(JavaThread* thread) {
- // After any safepoint, just before going back to compiled code,
- // we inform the GC that we will be doing initializing writes to
- // this object in the future without emitting card-marks, so
- // GC may take any compensating steps.
- // NOTE: Keep this code consistent with GraphKit::store_barrier.
-
- oop new_obj = thread->vm_result();
- if (new_obj == NULL) return;
-
- assert(Universe::heap()->can_elide_tlab_store_barriers(),
- "compiler must check this first");
- // GC may decide to give back a safer copy of new_obj.
- new_obj = Universe::heap()->new_store_pre_barrier(thread, new_obj);
- thread->set_vm_result(new_obj);
-}
-
// object allocation
JRT_BLOCK_ENTRY(void, OptoRuntime::new_instance_C(Klass* klass, JavaThread* thread))
JRT_BLOCK;
@@ -244,10 +227,8 @@
deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION);
JRT_BLOCK_END;
- if (GraphKit::use_ReduceInitialCardMarks()) {
- // inform GC that we won't do card marks for initializing writes.
- new_store_pre_barrier(thread);
- }
+ // inform GC that we won't do card marks for initializing writes.
+ SharedRuntime::on_slowpath_allocation_exit(thread);
JRT_END
@@ -284,10 +265,8 @@
thread->set_vm_result(result);
JRT_BLOCK_END;
- if (GraphKit::use_ReduceInitialCardMarks()) {
- // inform GC that we won't do card marks for initializing writes.
- new_store_pre_barrier(thread);
- }
+ // inform GC that we won't do card marks for initializing writes.
+ SharedRuntime::on_slowpath_allocation_exit(thread);
JRT_END
// array allocation without zeroing
@@ -314,10 +293,9 @@
thread->set_vm_result(result);
JRT_BLOCK_END;
- if (GraphKit::use_ReduceInitialCardMarks()) {
- // inform GC that we won't do card marks for initializing writes.
- new_store_pre_barrier(thread);
- }
+
+ // inform GC that we won't do card marks for initializing writes.
+ SharedRuntime::on_slowpath_allocation_exit(thread);
oop result = thread->vm_result();
if ((len > 0) && (result != NULL) &&
--- a/src/hotspot/share/opto/runtime.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/opto/runtime.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, 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
@@ -163,10 +163,6 @@
static void new_array_C(Klass* array_klass, int len, JavaThread *thread);
static void new_array_nozero_C(Klass* array_klass, int len, JavaThread *thread);
- // Post-slow-path-allocation, pre-initializing-stores step for
- // implementing ReduceInitialCardMarks
- static void new_store_pre_barrier(JavaThread* thread);
-
// Allocate storage for a multi-dimensional arrays
// Note: needs to be fixed for arbitrary number of dimensions
static void multianewarray2_C(Klass* klass, int len1, int len2, JavaThread *thread);
--- a/src/hotspot/share/runtime/sharedRuntime.cpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -3169,3 +3169,16 @@
}
return activation;
}
+
+void SharedRuntime::on_slowpath_allocation_exit(JavaThread* thread) {
+ // After any safepoint, just before going back to compiled code,
+ // we inform the GC that we will be doing initializing writes to
+ // this object in the future without emitting card-marks, so
+ // GC may take any compensating steps.
+
+ oop new_obj = thread->vm_result();
+ if (new_obj == NULL) return;
+
+ BarrierSet *bs = Universe::heap()->barrier_set();
+ bs->on_slowpath_allocation_exit(thread, new_obj);
+}
--- a/src/hotspot/share/runtime/sharedRuntime.hpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/runtime/sharedRuntime.hpp Wed Jan 10 22:48:27 2018 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -211,6 +211,10 @@
static address deoptimize_for_implicit_exception(JavaThread* thread, address pc, CompiledMethod* nm, int deopt_reason);
#endif
+ // Post-slow-path-allocation, pre-initializing-stores step for
+ // implementing e.g. ReduceInitialCardMarks
+ static void on_slowpath_allocation_exit(JavaThread* thread);
+
static void enable_stack_reserved_zone(JavaThread* thread);
static frame look_for_reserved_stack_annotated_method(JavaThread* thread, frame fr);
--- a/src/hotspot/share/runtime/thread.cpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/runtime/thread.cpp Wed Jan 10 22:48:27 2018 +0100
@@ -1994,20 +1994,10 @@
JvmtiExport::cleanup_thread(this);
}
- // We must flush any deferred card marks before removing a thread from
- // the list of active threads.
- Universe::heap()->flush_deferred_store_barrier(this);
- assert(deferred_card_mark().is_empty(), "Should have been flushed");
-
-#if INCLUDE_ALL_GCS
- // We must flush the G1-related buffers before removing a thread
- // from the list of active threads. We must do this after any deferred
- // card marks have been flushed (above) so that any entries that are
- // added to the thread's dirty card queue as a result are not lost.
- if (UseG1GC) {
- flush_barrier_queues();
- }
-#endif // INCLUDE_ALL_GCS
+ // We must flush any deferred card marks and other various GC barrier
+ // related buffers (e.g. G1 SATB buffer and G1 dirty card queue buffer)
+ // before removing a thread from the list of active threads.
+ BarrierSet::barrier_set()->flush_deferred_barriers(this);
log_info(os, thread)("JavaThread %s (tid: " UINTX_FORMAT ").",
exit_type == JavaThread::normal_exit ? "exiting" : "detaching",
--- a/src/hotspot/share/runtime/vmStructs.cpp Mon Feb 12 16:08:33 2018 -0800
+++ b/src/hotspot/share/runtime/vmStructs.cpp Wed Jan 10 22:48:27 2018 +0100
@@ -466,6 +466,7 @@
nonstatic_field(CardGeneration, _capacity_at_prologue, size_t) \
nonstatic_field(CardGeneration, _used_at_prologue, size_t) \
\
+ nonstatic_field(CardTableModRefBS, _defer_initial_card_mark, bool) \
nonstatic_field(CardTableModRefBS, _whole_heap, const MemRegion) \
nonstatic_field(CardTableModRefBS, _guard_index, const size_t) \
nonstatic_field(CardTableModRefBS, _last_valid_index, const size_t) \
@@ -482,7 +483,6 @@
\
nonstatic_field(CollectedHeap, _reserved, MemRegion) \
nonstatic_field(CollectedHeap, _barrier_set, BarrierSet*) \
- nonstatic_field(CollectedHeap, _defer_initial_card_mark, bool) \
nonstatic_field(CollectedHeap, _is_gc_active, bool) \
nonstatic_field(CollectedHeap, _total_collections, unsigned int) \
\