Some methods can be moved to subclasses. Originally, the superclass needs to be used because we don't know the concrete type statically. Now, almost all callers have the concrete type, so many (virtual) methods can be moved to subclasses.
Such as, unimplemented methods:
// Allocate and returns a block of the requested size, or returns "null".
// Assumes the caller has done any necessary locking.
virtual HeapWord* allocate(size_t word_size, bool is_tlab) = 0;
// Like "allocate", but performs any necessary locking internally.
virtual HeapWord* par_allocate(size_t word_size, bool is_tlab) = 0;
and more ending with `= 0;`.
and probably other kinds of methods that have different implementations for the two subclasses, e.g. supports_tlab_allocation.
Such as, unimplemented methods:
// Allocate and returns a block of the requested size, or returns "null".
// Assumes the caller has done any necessary locking.
virtual HeapWord* allocate(size_t word_size, bool is_tlab) = 0;
// Like "allocate", but performs any necessary locking internally.
virtual HeapWord* par_allocate(size_t word_size, bool is_tlab) = 0;
and more ending with `= 0;`.
and probably other kinds of methods that have different implementations for the two subclasses, e.g. supports_tlab_allocation.