--- old/src/hotspot/share/memory/iterator.inline.hpp 2018-06-20 11:50:29.808139342 +0200 +++ new/src/hotspot/share/memory/iterator.inline.hpp 2018-06-20 11:50:29.584139349 +0200 @@ -38,21 +38,21 @@ #include "oops/typeArrayKlass.inline.hpp" #include "utilities/debug.hpp" -inline void MetadataAwareOopClosure::do_cld_nv(ClassLoaderData* cld) { +inline void MetadataVisitingOopIterateClosure::do_cld(ClassLoaderData* cld) { bool claim = true; // Must claim the class loader data before processing. cld->oops_do(this, claim); } -inline void MetadataAwareOopClosure::do_klass_nv(Klass* k) { +inline void MetadataVisitingOopIterateClosure::do_klass(Klass* k) { ClassLoaderData* cld = k->class_loader_data(); - do_cld_nv(cld); + MetadataVisitingOopIterateClosure::do_cld(cld); } #ifdef ASSERT // This verification is applied to all visited oops. // The closures can turn is off by overriding should_verify_oops(). template -void ExtendedOopClosure::verify(T* p) { +void OopIterateClosure::verify(T* p) { if (should_verify_oops()) { T heap_oop = RawAccess<>::oop_load(p); if (!CompressedOops::is_null(heap_oop)) { @@ -65,54 +65,366 @@ #endif // Implementation of the non-virtual do_oop dispatch. +// +// The same implementation is used for do_metadata, do_klass, and do_cld. +// +// Preconditions: +// - Base has a pure virtual do_oop +// - Only one of the classes in the inheritance chain from OopClosureType to +// Base implements do_oop. +// +// Given the preconditions: +// - If &OopClosureType::do_oop is resolved to &Base::do_oop, then there are no +// implementation of do_oop between Base and OopClosureType. However, there +// must be one implementation in one of the subclasses of OopClosureType. +// In this case we take the virtual call. +// +// - Conversely, if &OopClosureType::do_oop is not resolved to &Base::do_oop, +// then we've found the one and only concrete implementation. In this case we +// take a non-virtual call. +// +// Because of this it's clear when we should call the virtual call and +// when the non-virtual call should be made. +// +// The way we find if &OopClosureType::do_oop is resolved to &Base::do_oop is to +// check if the resulting type of the class of a member-function pointer to +// &OopClosureType::do_oop is equal to the type of the class of a +// &Base::do_oop member-function pointer. Template parameter deduction is used +// to find these types, and then the IsSame trait is used to check if they are +// equal. Finally, SFINAE is used to select the appropriate implementation. +// +// Template parameters: +// T - narrowOop or oop +// Receiver - the resolved type of the class of the +// &OopClosureType::do_oop member-function pointer. That is, +// the klass with the do_oop member function. +// Base - klass with the pure virtual do_oop member function. +// OopClosureType - The dynamic closure type +// +// Parameters: +// closure - The closure to call +// p - The oop (or narrowOop) field to pass to the closure -template -inline void Devirtualizer::do_oop(OopClosureType* closure, T* p) { - debug_only(closure->verify(p)); - closure->do_oop_nv(p); +template +static typename EnableIf::value, void>::type +call_do_oop(void (Receiver::*)(T*), void (Base::*)(T*), OopClosureType* closure, T* p) { + closure->do_oop(p); } -template -inline void Devirtualizer::do_klass(OopClosureType* closure, Klass* k) { - closure->do_klass_nv(k); + +template +static typename EnableIf::value, void>::type +call_do_oop(void (Receiver::*)(T*), void (Base::*)(T*), OopClosureType* closure, T* p) { + // Sanity check + STATIC_ASSERT((!IsSame::value)); + closure->OopClosureType::do_oop(p); } -template -void Devirtualizer::do_cld(OopClosureType* closure, ClassLoaderData* cld) { - closure->do_cld_nv(cld); + +template +inline void Devirtualizer::do_oop_no_verify(OopClosureType* closure, T* p) { + call_do_oop(&OopClosureType::do_oop, &OopClosure::do_oop, closure, p); } -template -inline bool Devirtualizer::do_metadata(OopClosureType* closure) { - // Make sure the non-virtual and the virtual versions match. - assert(closure->do_metadata_nv() == closure->do_metadata(), "Inconsistency in do_metadata"); - return closure->do_metadata_nv(); + +template +inline void Devirtualizer::do_oop(OopClosureType* closure, T* p) { + debug_only(closure->verify(p)); + + do_oop_no_verify(closure, p); } -// Implementation of the virtual do_oop dispatch. +// Implementation of the non-virtual do_metadata dispatch. -template -void Devirtualizer::do_oop(OopClosureType* closure, T* p) { - debug_only(closure->verify(p)); - closure->do_oop(p); +template +static typename EnableIf::value, bool>::type +call_do_metadata(bool (Receiver::*)(), bool (Base::*)(), OopClosureType* closure) { + return closure->do_metadata(); +} + +template +static typename EnableIf::value, bool>::type +call_do_metadata(bool (Receiver::*)(), bool (Base::*)(), OopClosureType* closure) { + return closure->OopClosureType::do_metadata(); } -template -void Devirtualizer::do_klass(OopClosureType* closure, Klass* k) { + +template +inline bool Devirtualizer::do_metadata(OopClosureType* closure) { + return call_do_metadata(&OopClosureType::do_metadata, &OopIterateClosure::do_metadata, closure); +} + +// Implementation of the non-virtual do_klass dispatch. + +template +static typename EnableIf::value, void>::type +call_do_klass(void (Receiver::*)(Klass*), void (Base::*)(Klass*), OopClosureType* closure, Klass* k) { closure->do_klass(k); } -template -void Devirtualizer::do_cld(OopClosureType* closure, ClassLoaderData* cld) { + +template +static typename EnableIf::value, void>::type +call_do_klass(void (Receiver::*)(Klass*), void (Base::*)(Klass*), OopClosureType* closure, Klass* k) { + closure->OopClosureType::do_klass(k); +} + +template +inline void Devirtualizer::do_klass(OopClosureType* closure, Klass* k) { + call_do_klass(&OopClosureType::do_klass, &OopIterateClosure::do_klass, closure, k); +} + +// Implementation of the non-virtual do_cld dispatch. + +template +static typename EnableIf::value, void>::type +call_do_cld(void (Receiver::*)(ClassLoaderData*), void (Base::*)(ClassLoaderData*), OopClosureType* closure, ClassLoaderData* cld) { closure->do_cld(cld); } -template -bool Devirtualizer::do_metadata(OopClosureType* closure) { - return closure->do_metadata(); + +template +static typename EnableIf::value, void>::type +call_do_cld(void (Receiver::*)(ClassLoaderData*), void (Base::*)(ClassLoaderData*), OopClosureType* closure, ClassLoaderData* cld) { + closure->OopClosureType::do_cld(cld); +} + +template +void Devirtualizer::do_cld(OopClosureType* closure, ClassLoaderData* cld) { + call_do_cld(&OopClosureType::do_cld, &OopIterateClosure::do_cld, closure, cld); +} + +// Dispatch table implementation for *Klass::oop_oop_iterate +// +// It allows for a single call to do a multi-dispatch to an optimized version +// of oop_oop_iterate that statically know all these types: +// - OopClosureType : static type give at call site +// - Klass* : dynamic to static type through Klass::id() -> table index +// - UseCompressedOops : dynamic to static value determined once +// +// when users call obj->oop_iterate(&cl). +// +// oopDesc::oop_iterate() calls OopOopIterateDispatch::function(klass)(cl, obj, klass), +// which dispatches to an optimized version of +// [Instance, ObjArry, etc]Klass::oop_oop_iterate(oop, OopClosureType) +// +// OopClosureType : +// If OopClosureType has an implementation of do_oop (and do_metadata et.al.), +// then the static type of OopClosureType will be used to allow inlining of +// do_oop (even though do_oop is virtual). Otherwise, a virtual call will be +// used when calling do_oop. +// +// Klass* : +// A table mapping from *Klass::ID to function is setup. This happens once +// when the program starts, when the static _table instance is initialized for +// the OopOopIterateDispatch specialized with the OopClosureType. +// +// UseCompressedOops : +// Initially the table is populated with an init function, and not the actual +// oop_oop_iterate function. This is done, so that the first time we dispatch +// through the init function we check what the value of UseCompressedOops +// became, and use that to determine if we should install an optimized +// narrowOop version or optimized oop version of oop_oop_iterate. The appropriate +// oop_oop_iterate function replaces the init function in the table, and +// succeeding calls will jump directly to oop_oop_iterate. + + +template +class OopOopIterateDispatch { +private: + class Table { + private: + static const int NUM_KLASSES = 6; + + template + static void oop_oop_iterate(OopClosureType* cl, oop obj, Klass* k) { + ((KlassType*)k)->KlassType::template oop_oop_iterate(obj, cl); + } + + template + static void init(OopClosureType* cl, oop obj, Klass* k) { + OopOopIterateDispatch::_table.set_resolve_function_and_execute(cl, obj, k); + } + + template + void set_init_function() { + _function[KlassType::ID] = &init; + } + + template + void set_resolve_function() { + // Size requirement to prevent word tearing + // when functions pointers are updated. + STATIC_ASSERT(sizeof(_function[0]) == sizeof(void*)); + if (UseCompressedOops) { + _function[KlassType::ID] = &oop_oop_iterate; + } else { + _function[KlassType::ID] = &oop_oop_iterate; + } + } + + template + void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k) { + set_resolve_function(); + _function[KlassType::ID](cl, obj, k); + } + + public: + void (*_function[NUM_KLASSES])(OopClosureType*, oop, Klass*); + + Table(){ + set_init_function(); + set_init_function(); + set_init_function(); + set_init_function(); + set_init_function(); + set_init_function(); + } + }; + + static Table _table; +public: + + static void (*function(Klass* klass))(OopClosureType*, oop, Klass*) { + return _table._function[klass->id()]; + } +}; + +template +typename OopOopIterateDispatch::Table OopOopIterateDispatch::_table; + + +template +class OopOopIterateBoundedDispatch { +private: + class Table { + private: + static const int NUM_KLASSES = 6; + + template + static void oop_oop_iterate_bounded(OopClosureType* cl, oop obj, Klass* k, MemRegion mr) { + ((KlassType*)k)->KlassType::template oop_oop_iterate_bounded(obj, cl, mr); + } + + template + static void init(OopClosureType* cl, oop obj, Klass* k, MemRegion mr) { + OopOopIterateBoundedDispatch::_table.set_resolve_function_and_execute(cl, obj, k, mr); + } + + template + void set_init_function() { + _function[KlassType::ID] = &init; + } + + template + void set_resolve_function() { + if (UseCompressedOops) { + _function[KlassType::ID] = &oop_oop_iterate_bounded; + } else { + _function[KlassType::ID] = &oop_oop_iterate_bounded; + } + } + + template + void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k, MemRegion mr) { + set_resolve_function(); + _function[KlassType::ID](cl, obj, k, mr); + } + + public: + void (*_function[NUM_KLASSES])(OopClosureType*, oop, Klass*, MemRegion); + + Table(){ + set_init_function(); + set_init_function(); + set_init_function(); + set_init_function(); + set_init_function(); + set_init_function(); + } + }; + + static Table _table; +public: + + static void (*function(Klass* klass))(OopClosureType*, oop, Klass*, MemRegion) { + return _table._function[klass->id()]; + } +}; + +template +typename OopOopIterateBoundedDispatch::Table OopOopIterateBoundedDispatch::_table; + + +template +class OopOopIterateBackwardsDispatch { +private: + class Table { + private: + static const int NUM_KLASSES = 6; + + template + static void oop_oop_iterate_backwards(OopClosureType* cl, oop obj, Klass* k) { + ((KlassType*)k)->KlassType::template oop_oop_iterate_reverse(obj, cl); + } + + template + static void init(OopClosureType* cl, oop obj, Klass* k) { + OopOopIterateBackwardsDispatch::_table.set_resolve_function_and_execute(cl, obj, k); + } + + template + void set_init_function() { + _function[KlassType::ID] = &init; + } + + template + void set_resolve_function() { + if (UseCompressedOops) { + _function[KlassType::ID] = &oop_oop_iterate_backwards; + } else { + _function[KlassType::ID] = &oop_oop_iterate_backwards; + } + } + + template + void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k) { + set_resolve_function(); + _function[KlassType::ID](cl, obj, k); + } + + public: + void (*_function[NUM_KLASSES])(OopClosureType*, oop, Klass*); + + Table(){ + set_init_function(); + set_init_function(); + set_init_function(); + set_init_function(); + set_init_function(); + set_init_function(); + } + }; + + static Table _table; +public: + + static void (*function(Klass* klass))(OopClosureType*, oop, Klass*) { + return _table._function[klass->id()]; + } +}; + +template +typename OopOopIterateBackwardsDispatch::Table OopOopIterateBackwardsDispatch::_table; + + +template +void OopClosureDispatch::oop_oop_iterate(OopClosureType* cl, oop obj, Klass* klass) { + OopOopIterateDispatch::function(klass)(cl, obj, klass); } -// The list of all "specializable" oop_oop_iterate function definitions. -#define ALL_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ - ALL_INSTANCE_KLASS_OOP_OOP_ITERATE_DEFN( OopClosureType, nv_suffix) \ - ALL_INSTANCE_REF_KLASS_OOP_OOP_ITERATE_DEFN( OopClosureType, nv_suffix) \ - ALL_INSTANCE_MIRROR_KLASS_OOP_OOP_ITERATE_DEFN( OopClosureType, nv_suffix) \ - ALL_INSTANCE_CLASS_LOADER_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ - ALL_OBJ_ARRAY_KLASS_OOP_OOP_ITERATE_DEFN( OopClosureType, nv_suffix) \ - ALL_TYPE_ARRAY_KLASS_OOP_OOP_ITERATE_DEFN( OopClosureType, nv_suffix) +template +void OopClosureDispatch::oop_oop_iterate(OopClosureType* cl, oop obj, Klass* klass, MemRegion mr) { + OopOopIterateBoundedDispatch::function(klass)(cl, obj, klass, mr); +} + +template +void OopClosureDispatch::oop_oop_iterate_backwards(OopClosureType* cl, oop obj, Klass* klass) { + OopOopIterateBackwardsDispatch::function(klass)(cl, obj, klass); +} #endif // SHARE_VM_MEMORY_ITERATOR_INLINE_HPP