Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8082982 | emb-9 | Kim Barrett | P4 | Resolved | Fixed | team |
The barrier set is typically stored and obtained as a BarrierSet base object, with many users then downcasting to a more specific derived class.
(1) Sometimes that downcast is known to be safe, from context. An example of this is G1CollectedHeap::g1_barrier_set(). [But that could be pretty limiting if we decide we need more barrier set kinds for G1 variants/options.]
(2) Sometimes that downcast is checked via a preceding assert using BarrierSet::is_a() with a corresponding tag. It's an assert rather than a guarantee because the present implementation of is_a() is not fast. [I haven't studied all such occurrences to see if they are performance critical.] This is a stand-in for dynamic_cast, in the absence of RTTI support.
(3) Sometimes the downcast is just blindly done, and hope for the best. Probably at least some of these cases really fall into (1) above, but are not obviously so. And some of them might just be bugs waiting to happen.
We can do better than this.
My current thought is to add something like the following:
template<typename T> T* barrier_set_cast(BarrierSet* bs);
template<typename T> T const* barrier_set_cast(BarrierSet const* bs);
Return bs downcasted to corresponding pointer to T, if the actual
type of *bs is derived from T. Otherwise error.
template<typename T> struct GetBarrierSetName;
Provides value member of type BarrierSet::Name corresponding to T.
For each T that will be used with barrier_set_cast, there must be a corresponding specialization of GetBarrierSetName.
Add uintx BarrierSet::_kind_set, which is a bitset indicating the BarrierSet::Name tags that apply to the barrier set. Appropriate bits in _kind_set are set by the corresponding derived class constructors.
The implementation of barrier_set_cast can validate the cast by using GetBarrierSetName to get the corresponding tag value, and test whether the corresponding bit is set in _kind_set. This can be an assert, and is sufficiently light-weight that a guarantee can be considered.
(1) Sometimes that downcast is known to be safe, from context. An example of this is G1CollectedHeap::g1_barrier_set(). [But that could be pretty limiting if we decide we need more barrier set kinds for G1 variants/options.]
(2) Sometimes that downcast is checked via a preceding assert using BarrierSet::is_a() with a corresponding tag. It's an assert rather than a guarantee because the present implementation of is_a() is not fast. [I haven't studied all such occurrences to see if they are performance critical.] This is a stand-in for dynamic_cast, in the absence of RTTI support.
(3) Sometimes the downcast is just blindly done, and hope for the best. Probably at least some of these cases really fall into (1) above, but are not obviously so. And some of them might just be bugs waiting to happen.
We can do better than this.
My current thought is to add something like the following:
template<typename T> T* barrier_set_cast(BarrierSet* bs);
template<typename T> T const* barrier_set_cast(BarrierSet const* bs);
Return bs downcasted to corresponding pointer to T, if the actual
type of *bs is derived from T. Otherwise error.
template<typename T> struct GetBarrierSetName;
Provides value member of type BarrierSet::Name corresponding to T.
For each T that will be used with barrier_set_cast, there must be a corresponding specialization of GetBarrierSetName.
Add uintx BarrierSet::_kind_set, which is a bitset indicating the BarrierSet::Name tags that apply to the barrier set. Appropriate bits in _kind_set are set by the corresponding derived class constructors.
The implementation of barrier_set_cast can validate the cast by using GetBarrierSetName to get the corresponding tag value, and test whether the corresponding bit is set in _kind_set. This can be an assert, and is sufficiently light-weight that a guarantee can be considered.
- backported by
-
JDK-8082982 Add BarrierSet downcast support
-
- Resolved
-
- blocks
-
JDK-8074319 barrier_set_cast defined via friend injection
-
- Resolved
-
-
JDK-8067891 Remove vestigal G1SATBCT barrier set kind
-
- Resolved
-
- is blocked by
-
JDK-8069230 Remove unused G1PostBarrierStub::byte_map_base and friends
-
- Resolved
-