diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 98ede25b88df5..2d5cef8fd6dee 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,3 @@ # Contributing to the JDK - +... Please see the [OpenJDK Developers' Guide](https://openjdk.org/guide/). diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 3bb4030afdeda..540b24f5c78ec 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -268,26 +268,36 @@ class nmethod : public CodeBlob { volatile signed char _state; // {not_installed, in_use, not_entrant} public: - union Flags { - uint8_t _raw; - struct { - bool _has_unsafe_access:1; // May fault due to unsafe access. - bool _has_wide_vectors:1; // Preserve wide vectors at safepoints - bool _has_monitors:1; // Fastpath monitor detection for continuations - bool _has_scoped_access:1; // Used by shared scope closure (scopedMemoryAccess.cpp) + struct Flags { + uint8_t const _bits; + + enum : uint8_t { + UNSAFE_ACCESS = 1 << 0, + WIDE_VECTORS = 1 << 1, + MONITORS = 1 << 2, + SCOPED_ACCESS = 1 << 3 }; - Flags() { - _raw = 0; - } - Flags(bool has_unsafe_access, bool has_wide_vectors, bool has_monitors, bool has_scoped_access) : Flags() { - _has_unsafe_access = has_unsafe_access; - _has_wide_vectors = has_wide_vectors; - _has_monitors = has_monitors; - _has_scoped_access = has_scoped_access; - } - }; - static_assert(sizeof(Flags) == sizeof(uint8_t), "Must fit exactly"); + Flags() : _bits(0) {} + Flags(bool has_unsafe_access, bool has_wide_vectors, bool has_monitors, bool has_scoped_access) : + _bits((has_unsafe_access ? UNSAFE_ACCESS : 0) | + (has_wide_vectors ? WIDE_VECTORS : 0) | + (has_monitors ? MONITORS : 0) | + (has_scoped_access ? SCOPED_ACCESS : 0)) + {} + + // May fault due to unsafe access + bool has_unsafe_access() const { return (_bits & UNSAFE_ACCESS) != 0; } + + // Preserve wide vectors at safepoints + bool has_wide_vectors() const { return (_bits & WIDE_VECTORS) != 0; } + + // Fastpath monitor detection for continuations + bool has_monitors() const { return (_bits & MONITORS) != 0; } + + // Used by shared scope closure (scopedMemoryAccess.cpp) + bool has_scoped_access() const { return (_bits & SCOPED_ACCESS) != 0; } + }; private: // Persistent bits, set once during construction. @@ -779,10 +789,10 @@ class nmethod : public CodeBlob { template void set_gc_data(T* gc_data) { _gc_data = reinterpret_cast(gc_data); } - bool has_unsafe_access() const { return _flags._has_unsafe_access; } - bool has_monitors() const { return _flags._has_monitors; } - bool has_scoped_access() const { return _flags._has_scoped_access; } - bool has_wide_vectors() const { return _flags._has_wide_vectors; } + bool has_unsafe_access() const { return _flags.has_unsafe_access(); } + bool has_monitors() const { return _flags.has_monitors(); } + bool has_scoped_access() const { return _flags.has_scoped_access(); } + bool has_wide_vectors() const { return _flags.has_wide_vectors(); } bool has_flushed_dependencies() const { return _has_flushed_dependencies; } void set_has_flushed_dependencies(bool z) { diff --git a/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp b/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp index a486a88c48fbc..0a03ce52e238b 100644 --- a/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp +++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.hpp @@ -324,6 +324,8 @@ class BarrierSetC2: public CHeapObj { virtual bool is_gc_pre_barrier_node(Node* node) const { return false; } virtual bool is_gc_barrier_node(Node* node) const { return false; } virtual Node* step_over_gc_barrier(Node* c) const { return c; } + // Allow barriers that depend on transitive inputs to be re-evaluated. + virtual void enqueue_dependent_gc_barriers(Unique_Node_List& worklist, Node* use) const {} // Support for macro expanded GC barriers virtual void register_potential_barrier_node(Node* node) const { } diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp index deab648a108ec..f786702a29190 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp @@ -843,6 +843,36 @@ Node* ShenandoahBarrierSetC2::step_over_gc_barrier(Node* c) const { return c; } +static bool is_barrier_traversal_node(int op) { + // Node types that ShenandoahLoadReferenceBarrierNode::Identity traverses via needs_barrier_impl. + return op == Op_Phi || op == Op_DecodeN || op == Op_EncodeP || op == Op_CastPP || + op == Op_CheckCastPP || op == Op_CMoveN || op == Op_CMoveP || op == Op_Proj; +} + +void ShenandoahBarrierSetC2::enqueue_dependent_gc_barriers(Unique_Node_List& worklist, Node* n) const { + if (!is_barrier_traversal_node(n->Opcode())) { + return; + } + Unique_Node_List visited; + Unique_Node_List stack; + stack.push(n); + while (stack.size() > 0) { + Node* cur = stack.pop(); + if (visited.member(cur)) { + continue; + } + visited.push(cur); + for (DUIterator_Fast imax, i = cur->fast_outs(imax); i < imax; i++) { + Node* u = cur->fast_out(i); + if (u->Opcode() == Op_ShenandoahLoadReferenceBarrier) { + worklist.push(u); + } else if (is_barrier_traversal_node(u->Opcode())) { + stack.push(u); + } + } + } +} + bool ShenandoahBarrierSetC2::expand_barriers(Compile* C, PhaseIterGVN& igvn) const { return !ShenandoahBarrierC2Support::expand(C, igvn); } diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp index c77a9da63fc1b..63244ee7751ea 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp @@ -127,6 +127,7 @@ class ShenandoahBarrierSetC2 : public BarrierSetC2 { virtual bool is_gc_pre_barrier_node(Node* node) const; virtual bool is_gc_barrier_node(Node* node) const; virtual Node* step_over_gc_barrier(Node* c) const; + virtual void enqueue_dependent_gc_barriers(Unique_Node_List& worklist, Node* use) const; virtual bool expand_barriers(Compile* C, PhaseIterGVN& igvn) const; virtual bool optimize_loops(PhaseIdealLoop* phase, LoopOptsMode mode, VectorSet& visited, Node_Stack& nstack, Node_List& worklist) const; virtual bool strip_mined_loops_expanded(LoopOptsMode mode) const { return mode == LoopOptsShenandoahExpand; } diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index a4d6a6c33d081..c166a3f05f79d 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -2797,6 +2797,11 @@ void PhaseIterGVN::add_users_of_use_to_worklist(Node* n, Node* use, Unique_Node_ add_users_to_worklist_if(worklist, use, [](Node* u) { return u->Opcode() == Op_VectorMaskToLong; }); } + // Allow GC to enqueue barriers that depend on transitive inputs + if (has_load_barrier_nodes) { + bs->enqueue_dependent_gc_barriers(worklist, use); + } + // From CastX2PNode::Ideal // CastX2P(AddX(x, y)) // CastX2P(SubX(x, y))