163 lines
6.6 KiB
Diff
163 lines
6.6 KiB
Diff
|
|
# HG changeset patch
|
||
|
|
# User kbarrett
|
||
|
|
# Date 1473955843 14400
|
||
|
|
# Thu Sep 15 12:10:43 2016 -0400
|
||
|
|
# Node ID f008248d98dd625b62b5f3f5ca9b24956d33c18d
|
||
|
|
# Parent 7767224562139a10efca0575c28a62be7895d5b3
|
||
|
|
8165808: Add release barriers when allocating objects with concurrent collection
|
||
|
|
Summary: Add release_set_klass, use in slow-path allocators.
|
||
|
|
Reviewed-by: jmasa, dholmes
|
||
|
|
|
||
|
|
diff --git a/src/share/vm/gc_interface/collectedHeap.hpp b/src/share/vm/gc_interface/collectedHeap.hpp
|
||
|
|
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp
|
||
|
|
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp
|
||
|
|
@@ -320,9 +320,6 @@
|
||
|
|
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 void post_allocation_install_obj_klass(KlassHandle klass,
|
||
|
|
- oop obj);
|
||
|
|
-
|
||
|
|
// Raw memory allocation facilities
|
||
|
|
// The obj and array allocate methods are covers for these methods.
|
||
|
|
// mem_allocate() should never be
|
||
|
|
diff --git a/src/share/vm/gc_interface/collectedHeap.inline.hpp b/src/share/vm/gc_interface/collectedHeap.inline.hpp
|
||
|
|
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp
|
||
|
|
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp
|
||
|
|
@@ -39,14 +39,22 @@
|
||
|
|
// Inline allocation implementations.
|
||
|
|
|
||
|
|
void CollectedHeap::post_allocation_setup_common(KlassHandle klass,
|
||
|
|
- HeapWord* obj) {
|
||
|
|
- post_allocation_setup_no_klass_install(klass, obj);
|
||
|
|
- post_allocation_install_obj_klass(klass, oop(obj));
|
||
|
|
+ HeapWord* obj_ptr) {
|
||
|
|
+ post_allocation_setup_no_klass_install(klass, obj_ptr);
|
||
|
|
+ oop obj = (oop)obj_ptr;
|
||
|
|
+#if ! INCLUDE_ALL_GCS
|
||
|
|
+ obj->set_klass(klass());
|
||
|
|
+#else
|
||
|
|
+ // Need a release store to ensure array/class length, mark word, and
|
||
|
|
+ // object zeroing are visible before setting the klass non-NULL, for
|
||
|
|
+ // concurrent collectors.
|
||
|
|
+ obj->release_set_klass(klass());
|
||
|
|
+#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void CollectedHeap::post_allocation_setup_no_klass_install(KlassHandle klass,
|
||
|
|
- HeapWord* objPtr) {
|
||
|
|
- oop obj = (oop)objPtr;
|
||
|
|
+ HeapWord* obj_ptr) {
|
||
|
|
+ oop obj = (oop)obj_ptr;
|
||
|
|
|
||
|
|
assert(obj != NULL, "NULL object pointer");
|
||
|
|
if (UseBiasedLocking && (klass() != NULL)) {
|
||
|
|
@@ -57,18 +65,6 @@
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
-void CollectedHeap::post_allocation_install_obj_klass(KlassHandle klass,
|
||
|
|
- oop obj) {
|
||
|
|
- // These asserts are kind of complicated because of klassKlass
|
||
|
|
- // and the beginning of the world.
|
||
|
|
- assert(klass() != NULL || !Universe::is_fully_initialized(), "NULL klass");
|
||
|
|
- assert(klass() == NULL || klass()->is_klass(), "not a klass");
|
||
|
|
- assert(obj != NULL, "NULL object pointer");
|
||
|
|
- obj->set_klass(klass());
|
||
|
|
- assert(!Universe::is_fully_initialized() || obj->klass() != NULL,
|
||
|
|
- "missing klass");
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
// Support for jvmti and dtrace
|
||
|
|
inline void post_allocation_notify(KlassHandle klass, oop obj, int size) {
|
||
|
|
// support low memory notifications (no-op if not enabled)
|
||
|
|
@@ -86,25 +82,26 @@
|
||
|
|
}
|
||
|
|
|
||
|
|
void CollectedHeap::post_allocation_setup_obj(KlassHandle klass,
|
||
|
|
- HeapWord* obj,
|
||
|
|
+ HeapWord* obj_ptr,
|
||
|
|
int size) {
|
||
|
|
- post_allocation_setup_common(klass, obj);
|
||
|
|
+ post_allocation_setup_common(klass, obj_ptr);
|
||
|
|
+ oop obj = (oop)obj_ptr;
|
||
|
|
assert(Universe::is_bootstrapping() ||
|
||
|
|
- !((oop)obj)->is_array(), "must not be an array");
|
||
|
|
+ !obj->is_array(), "must not be an array");
|
||
|
|
// notify jvmti and dtrace
|
||
|
|
- post_allocation_notify(klass, (oop)obj, size);
|
||
|
|
+ post_allocation_notify(klass, obj, size);
|
||
|
|
}
|
||
|
|
|
||
|
|
void CollectedHeap::post_allocation_setup_array(KlassHandle klass,
|
||
|
|
- HeapWord* obj,
|
||
|
|
+ HeapWord* obj_ptr,
|
||
|
|
int length) {
|
||
|
|
- // Set array length before setting the _klass field
|
||
|
|
- // in post_allocation_setup_common() because the klass field
|
||
|
|
- // indicates that the object is parsable by concurrent GC.
|
||
|
|
+ // Set array length before setting the _klass field because a
|
||
|
|
+ // non-NULL klass field indicates that the object is parsable by
|
||
|
|
+ // concurrent GC.
|
||
|
|
assert(length >= 0, "length should be non-negative");
|
||
|
|
- ((arrayOop)obj)->set_length(length);
|
||
|
|
- post_allocation_setup_common(klass, obj);
|
||
|
|
- oop new_obj = (oop)obj;
|
||
|
|
+ ((arrayOop)obj_ptr)->set_length(length);
|
||
|
|
+ post_allocation_setup_common(klass, obj_ptr);
|
||
|
|
+ oop new_obj = (oop)obj_ptr;
|
||
|
|
assert(new_obj->is_array(), "must be an array");
|
||
|
|
// notify jvmti and dtrace (must be after length is set for dtrace)
|
||
|
|
post_allocation_notify(klass, new_obj, new_obj->size());
|
||
|
|
diff --git a/src/share/vm/oops/oop.hpp b/src/share/vm/oops/oop.hpp
|
||
|
|
--- a/hotspot/src/share/vm/oops/oop.hpp
|
||
|
|
+++ b/hotspot/src/share/vm/oops/oop.hpp
|
||
|
|
@@ -87,6 +87,7 @@
|
||
|
|
narrowKlass* compressed_klass_addr();
|
||
|
|
|
||
|
|
void set_klass(Klass* k);
|
||
|
|
+ void release_set_klass(Klass* k);
|
||
|
|
|
||
|
|
// For klass field compression
|
||
|
|
int klass_gap() const;
|
||
|
|
diff --git a/src/share/vm/oops/oop.inline.hpp b/src/share/vm/oops/oop.inline.hpp
|
||
|
|
--- a/hotspot/src/share/vm/oops/oop.inline.hpp
|
||
|
|
+++ b/hotspot/src/share/vm/oops/oop.inline.hpp
|
||
|
|
@@ -103,10 +103,14 @@
|
||
|
|
return &_metadata._compressed_klass;
|
||
|
|
}
|
||
|
|
|
||
|
|
+#define CHECK_SET_KLASS(k) \
|
||
|
|
+ do { \
|
||
|
|
+ assert(Universe::is_bootstrapping() || k != NULL, "NULL Klass"); \
|
||
|
|
+ assert(Universe::is_bootstrapping() || k->is_klass(), "not a Klass"); \
|
||
|
|
+ } while (0)
|
||
|
|
+
|
||
|
|
inline void oopDesc::set_klass(Klass* k) {
|
||
|
|
- // since klasses are promoted no store check is needed
|
||
|
|
- assert(Universe::is_bootstrapping() || k != NULL, "must be a real Klass*");
|
||
|
|
- assert(Universe::is_bootstrapping() || k->is_klass(), "not a Klass*");
|
||
|
|
+ CHECK_SET_KLASS(k);
|
||
|
|
if (UseCompressedClassPointers) {
|
||
|
|
*compressed_klass_addr() = Klass::encode_klass_not_null(k);
|
||
|
|
} else {
|
||
|
|
@@ -114,6 +118,18 @@
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
+inline void oopDesc::release_set_klass(Klass* k) {
|
||
|
|
+ CHECK_SET_KLASS(k);
|
||
|
|
+ if (UseCompressedClassPointers) {
|
||
|
|
+ OrderAccess::release_store(compressed_klass_addr(),
|
||
|
|
+ Klass::encode_klass_not_null(k));
|
||
|
|
+ } else {
|
||
|
|
+ OrderAccess::release_store_ptr(klass_addr(), k);
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+#undef CHECK_SET_KLASS
|
||
|
|
+
|
||
|
|
inline int oopDesc::klass_gap() const {
|
||
|
|
return *(int*)(((intptr_t)this) + klass_gap_offset_in_bytes());
|
||
|
|
}
|