8229839: Break circular dependency between oop.inline.hpp and markWord.inline.hpp

Reviewed-by: pliden, tonyp
This commit is contained in:
Stefan Karlsson 2019-08-19 12:40:27 +02:00
parent a3d6be2b2d
commit ebf98ac78c
12 changed files with 91 additions and 88 deletions

View File

@ -8008,14 +8008,14 @@ void CMSCollector::preserve_mark_work(oop p, markWord m) {
// Single threaded
void CMSCollector::preserve_mark_if_necessary(oop p) {
markWord m = p->mark_raw();
if (m.must_be_preserved(p)) {
if (p->mark_must_be_preserved(m)) {
preserve_mark_work(p, m);
}
}
void CMSCollector::par_preserve_mark_if_necessary(oop p) {
markWord m = p->mark_raw();
if (m.must_be_preserved(p)) {
if (p->mark_must_be_preserved(m)) {
MutexLocker x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
// Even though we read the mark word without holding
// the lock, we are assured that it will not change

View File

@ -28,7 +28,7 @@
#include "gc/shared/genOopClosures.hpp"
#include "oops/compressedOops.inline.hpp"
#include "oops/markWord.inline.hpp"
#include "oops/oop.hpp"
#include "oops/oop.inline.hpp"
/////////////////////////////////////////////////////////////////////////
//// PromotionInfo

View File

@ -116,11 +116,11 @@ void G1FullGCCompactionPoint::forward(oop object, size_t size) {
} else {
// Make sure object has the correct mark-word set or that it will be
// fixed when restoring the preserved marks.
assert(object->mark_raw() == markWord::prototype_for_object(object) || // Correct mark
object->mark_raw().must_be_preserved(object) || // Will be restored by PreservedMarksSet
assert(object->mark_raw() == markWord::prototype_for_klass(object->klass()) || // Correct mark
object->mark_must_be_preserved() || // Will be restored by PreservedMarksSet
(UseBiasedLocking && object->has_bias_pattern_raw()), // Will be restored by BiasedLocking
"should have correct prototype obj: " PTR_FORMAT " mark: " PTR_FORMAT " prototype: " PTR_FORMAT,
p2i(object), object->mark_raw().value(), markWord::prototype_for_object(object).value());
p2i(object), object->mark_raw().value(), markWord::prototype_for_klass(object->klass()).value());
}
assert(object->forwardee() == NULL, "should be forwarded to NULL");
}

View File

@ -51,7 +51,7 @@ inline bool G1FullGCMarker::mark_object(oop obj) {
// Marked by us, preserve if needed.
markWord mark = obj->mark_raw();
if (mark.must_be_preserved(obj) &&
if (obj->mark_must_be_preserved(mark) &&
!G1ArchiveAllocator::is_open_archive_object(obj)) {
preserved_stack()->push(obj, mark);
}

View File

@ -77,11 +77,11 @@ template <class T> inline void G1AdjustClosure::adjust_pointer(T* p) {
oop forwardee = obj->forwardee();
if (forwardee == NULL) {
// Not forwarded, return current reference.
assert(obj->mark_raw() == markWord::prototype_for_object(obj) || // Correct mark
obj->mark_raw().must_be_preserved(obj) || // Will be restored by PreservedMarksSet
assert(obj->mark_raw() == markWord::prototype_for_klass(obj->klass()) || // Correct mark
obj->mark_must_be_preserved() || // Will be restored by PreservedMarksSet
(UseBiasedLocking && obj->has_bias_pattern_raw()), // Will be restored by BiasedLocking
"Must have correct prototype or be preserved, obj: " PTR_FORMAT ", mark: " PTR_FORMAT ", prototype: " PTR_FORMAT,
p2i(obj), obj->mark_raw().value(), markWord::prototype_for_object(obj).value());
p2i(obj), obj->mark_raw().value(), markWord::prototype_for_klass(obj->klass()).value());
return;
}

View File

@ -40,7 +40,7 @@ inline void MarkSweep::mark_object(oop obj) {
markWord mark = obj->mark_raw();
obj->set_mark_raw(markWord::prototype().set_marked());
if (mark.must_be_preserved(obj)) {
if (obj->mark_must_be_preserved(mark)) {
preserve_mark(obj, mark);
}
}

View File

@ -31,7 +31,7 @@
#include "utilities/stack.inline.hpp"
inline bool PreservedMarks::should_preserve_mark(oop obj, markWord m) const {
return m.must_be_preserved_for_promotion_failure(obj);
return obj->mark_must_be_preserved_for_promotion_failure(m);
}
inline void PreservedMarks::push(oop obj, markWord m) {

View File

@ -252,8 +252,8 @@ class markWord {
static markWord INFLATING() { return zero(); } // inflate-in-progress
// Should this header be preserved during GC?
inline bool must_be_preserved(oop obj_containing_mark) const;
inline bool must_be_preserved_with_bias(oop obj_containing_mark) const;
template <typename KlassProxy>
inline bool must_be_preserved(KlassProxy klass) const;
// Should this header (including its age bits) be preserved in the
// case of a promotion failure during scavenge?
@ -272,15 +272,14 @@ class markWord {
// observation is that promotion failures are quite rare and
// reducing the number of mark words preserved during them isn't a
// high priority.
inline bool must_be_preserved_for_promotion_failure(oop obj_containing_mark) const;
inline bool must_be_preserved_with_bias_for_promotion_failure(oop obj_containing_mark) const;
template <typename KlassProxy>
inline bool must_be_preserved_for_promotion_failure(KlassProxy klass) const;
// Should this header be preserved during a scavenge where CMS is
// the old generation?
// (This is basically the same body as must_be_preserved_for_promotion_failure(),
// but takes the Klass* as argument instead)
inline bool must_be_preserved_for_cms_scavenge(Klass* klass_of_obj_containing_mark) const;
inline bool must_be_preserved_with_bias_for_cms_scavenge(Klass* klass_of_obj_containing_mark) const;
// WARNING: The following routines are used EXCLUSIVELY by
// synchronization functions. They are not really gc safe.
@ -372,7 +371,7 @@ class markWord {
}
// Helper function for restoration of unmarked mark oops during GC
static inline markWord prototype_for_object(oop obj);
static inline markWord prototype_for_klass(const Klass* klass);
// Debugging
void print_on(outputStream* st) const;

View File

@ -27,88 +27,57 @@
#include "oops/klass.hpp"
#include "oops/markWord.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/globals.hpp"
// Should this header be preserved during GC (when biased locking is enabled)?
inline bool markWord::must_be_preserved_with_bias(oop obj_containing_mark) const {
assert(UseBiasedLocking, "unexpected");
if (has_bias_pattern()) {
// Will reset bias at end of collection
// Mark words of biased and currently locked objects are preserved separately
return false;
}
markWord prototype_header = prototype_for_object(obj_containing_mark);
if (prototype_header.has_bias_pattern()) {
// Individual instance which has its bias revoked; must return
// true for correctness
return true;
}
return (!is_unlocked() || !has_no_hash());
}
// Should this header be preserved during GC?
inline bool markWord::must_be_preserved(oop obj_containing_mark) const {
if (!UseBiasedLocking)
return (!is_unlocked() || !has_no_hash());
return must_be_preserved_with_bias(obj_containing_mark);
}
// Should this header be preserved in the case of a promotion failure
// during scavenge (when biased locking is enabled)?
inline bool markWord::must_be_preserved_with_bias_for_promotion_failure(oop obj_containing_mark) const {
assert(UseBiasedLocking, "unexpected");
// We don't explicitly save off the mark words of biased and
// currently-locked objects during scavenges, so if during a
// promotion failure we encounter either a biased mark word or a
// klass which still has a biasable prototype header, we have to
// preserve the mark word. This results in oversaving, but promotion
// failures are rare, and this avoids adding more complex logic to
// the scavengers to call new variants of
// BiasedLocking::preserve_marks() / restore_marks() in the middle
// of a scavenge when a promotion failure has first been detected.
if (has_bias_pattern() ||
prototype_for_object(obj_containing_mark).has_bias_pattern()) {
return true;
template <typename KlassProxy>
inline bool markWord::must_be_preserved(KlassProxy klass) const {
if (UseBiasedLocking) {
if (has_bias_pattern()) {
// Will reset bias at end of collection
// Mark words of biased and currently locked objects are preserved separately
return false;
}
markWord prototype_header = prototype_for_klass(klass);
if (prototype_header.has_bias_pattern()) {
// Individual instance which has its bias revoked; must return
// true for correctness
return true;
}
}
return (!is_unlocked() || !has_no_hash());
}
// Should this header be preserved in the case of a promotion failure
// during scavenge?
inline bool markWord::must_be_preserved_for_promotion_failure(oop obj_containing_mark) const {
if (!UseBiasedLocking)
return (!is_unlocked() || !has_no_hash());
return must_be_preserved_with_bias_for_promotion_failure(obj_containing_mark);
}
// Same as must_be_preserved_with_bias_for_promotion_failure() except that
// it takes a Klass* argument, instead of the object of which this is the mark word.
inline bool markWord::must_be_preserved_with_bias_for_cms_scavenge(Klass* klass_of_obj_containing_mark) const {
assert(UseBiasedLocking, "unexpected");
// CMS scavenges preserve mark words in similar fashion to promotion failures; see above
if (has_bias_pattern() ||
klass_of_obj_containing_mark->prototype_header().has_bias_pattern()) {
return true;
// Should this header be preserved in the case of a promotion failure during scavenge?
template <typename KlassProxy>
inline bool markWord::must_be_preserved_for_promotion_failure(KlassProxy klass) const {
if (UseBiasedLocking) {
// We don't explicitly save off the mark words of biased and
// currently-locked objects during scavenges, so if during a
// promotion failure we encounter either a biased mark word or a
// klass which still has a biasable prototype header, we have to
// preserve the mark word. This results in oversaving, but promotion
// failures are rare, and this avoids adding more complex logic to
// the scavengers to call new variants of
// BiasedLocking::preserve_marks() / restore_marks() in the middle
// of a scavenge when a promotion failure has first been detected.
if (has_bias_pattern() || prototype_for_klass(klass).has_bias_pattern()) {
return true;
}
}
return (!is_unlocked() || !has_no_hash());
}
// Same as must_be_preserved_for_promotion_failure() except that
// it takes a Klass* argument, instead of the object of which this is the mark word.
// Same as must_be_preserved_for_promotion_failure().
inline bool markWord::must_be_preserved_for_cms_scavenge(Klass* klass_of_obj_containing_mark) const {
if (!UseBiasedLocking)
return (!is_unlocked() || !has_no_hash());
return must_be_preserved_with_bias_for_cms_scavenge(klass_of_obj_containing_mark);
return must_be_preserved_for_promotion_failure(klass_of_obj_containing_mark);
}
inline markWord markWord::prototype_for_object(oop obj) {
#ifdef ASSERT
markWord prototype_header = obj->klass()->prototype_header();
inline markWord markWord::prototype_for_klass(const Klass* klass) {
markWord prototype_header = klass->prototype_header();
assert(prototype_header == prototype() || prototype_header.has_bias_pattern(), "corrupt prototype header");
#endif
return obj->klass()->prototype_header();
return prototype_header;
}
#endif // SHARE_OOPS_MARKWORD_INLINE_HPP

View File

@ -313,6 +313,11 @@ class oopDesc {
inline markWord displaced_mark_raw() const;
inline void set_displaced_mark_raw(markWord m);
// Checks if the mark word needs to be preserved
inline bool mark_must_be_preserved() const;
inline bool mark_must_be_preserved(markWord m) const;
inline bool mark_must_be_preserved_for_promotion_failure(markWord m) const;
static bool has_klass_gap();
// for code generation

View File

@ -82,11 +82,11 @@ markWord oopDesc::cas_set_mark_raw(markWord new_mark, markWord old_mark, atomic_
}
void oopDesc::init_mark() {
set_mark(markWord::prototype_for_object(this));
set_mark(markWord::prototype_for_klass(klass()));
}
void oopDesc::init_mark_raw() {
set_mark_raw(markWord::prototype_for_object(this));
set_mark_raw(markWord::prototype_for_klass(klass()));
}
Klass* oopDesc::klass() const {
@ -483,4 +483,34 @@ void oopDesc::set_displaced_mark_raw(markWord m) {
mark_raw().set_displaced_mark_helper(m);
}
// Supports deferred calling of obj->klass().
class DeferredObjectToKlass {
const oopDesc* _obj;
public:
DeferredObjectToKlass(const oopDesc* obj) : _obj(obj) {}
// Implicitly convertible to const Klass*.
operator const Klass*() const {
return _obj->klass();
}
};
bool oopDesc::mark_must_be_preserved() const {
return mark_must_be_preserved(mark_raw());
}
bool oopDesc::mark_must_be_preserved(markWord m) const {
// There's a circular dependency between oop.inline.hpp and
// markWord.inline.hpp because markWord::must_be_preserved wants to call
// oopDesc::klass(). This could be solved by calling klass() here. However,
// not all paths inside must_be_preserved calls klass(). Defer the call until
// the klass is actually needed.
return m.must_be_preserved(DeferredObjectToKlass(this));
}
bool oopDesc::mark_must_be_preserved_for_promotion_failure(markWord m) const {
return m.must_be_preserved_for_promotion_failure(DeferredObjectToKlass(this));
}
#endif // SHARE_OOPS_OOP_INLINE_HPP

View File

@ -1712,7 +1712,7 @@ inline void ObjectMarker::mark(oop o) {
// object's mark word
markWord mark = o->mark();
if (mark.must_be_preserved(o)) {
if (o->mark_must_be_preserved(mark)) {
_saved_mark_stack->push(mark);
_saved_oop_stack->push(o);
}