Path: blob/master/src/hotspot/share/memory/iterator.inline.hpp
40949 views
/*1* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_MEMORY_ITERATOR_INLINE_HPP25#define SHARE_MEMORY_ITERATOR_INLINE_HPP2627#include "memory/iterator.hpp"2829#include "classfile/classLoaderData.hpp"30#include "oops/access.inline.hpp"31#include "oops/compressedOops.inline.hpp"32#include "oops/klass.hpp"33#include "oops/instanceKlass.inline.hpp"34#include "oops/instanceMirrorKlass.inline.hpp"35#include "oops/instanceClassLoaderKlass.inline.hpp"36#include "oops/instanceRefKlass.inline.hpp"37#include "oops/objArrayKlass.inline.hpp"38#include "oops/typeArrayKlass.inline.hpp"39#include "utilities/debug.hpp"4041// Defaults to strong claiming.42inline MetadataVisitingOopIterateClosure::MetadataVisitingOopIterateClosure(ReferenceDiscoverer* rd) :43ClaimMetadataVisitingOopIterateClosure(ClassLoaderData::_claim_strong, rd) {}4445inline void ClaimMetadataVisitingOopIterateClosure::do_cld(ClassLoaderData* cld) {46cld->oops_do(this, _claim);47}4849inline void ClaimMetadataVisitingOopIterateClosure::do_klass(Klass* k) {50ClassLoaderData* cld = k->class_loader_data();51ClaimMetadataVisitingOopIterateClosure::do_cld(cld);52}5354// Implementation of the non-virtual do_oop dispatch.55//56// The same implementation is used for do_metadata, do_klass, and do_cld.57//58// Preconditions:59// - Base has a pure virtual do_oop60// - Only one of the classes in the inheritance chain from OopClosureType to61// Base implements do_oop.62//63// Given the preconditions:64// - If &OopClosureType::do_oop is resolved to &Base::do_oop, then there is no65// implementation of do_oop between Base and OopClosureType. However, there66// must be one implementation in one of the subclasses of OopClosureType.67// In this case we take the virtual call.68//69// - Conversely, if &OopClosureType::do_oop is not resolved to &Base::do_oop,70// then we've found the one and only concrete implementation. In this case we71// take a non-virtual call.72//73// Because of this it's clear when we should call the virtual call and74// when the non-virtual call should be made.75//76// The way we find if &OopClosureType::do_oop is resolved to &Base::do_oop is to77// check if the resulting type of the class of a member-function pointer to78// &OopClosureType::do_oop is equal to the type of the class of a79// &Base::do_oop member-function pointer. Template parameter deduction is used80// to find these types, and then the IsSame trait is used to check if they are81// equal. Finally, SFINAE is used to select the appropriate implementation.82//83// Template parameters:84// T - narrowOop or oop85// Receiver - the resolved type of the class of the86// &OopClosureType::do_oop member-function pointer. That is,87// the klass with the do_oop member function.88// Base - klass with the pure virtual do_oop member function.89// OopClosureType - The dynamic closure type90//91// Parameters:92// closure - The closure to call93// p - The oop (or narrowOop) field to pass to the closure9495template <typename T, typename Receiver, typename Base, typename OopClosureType>96static typename EnableIf<IsSame<Receiver, Base>::value, void>::type97call_do_oop(void (Receiver::*)(T*), void (Base::*)(T*), OopClosureType* closure, T* p) {98closure->do_oop(p);99}100101template <typename T, typename Receiver, typename Base, typename OopClosureType>102static typename EnableIf<!IsSame<Receiver, Base>::value, void>::type103call_do_oop(void (Receiver::*)(T*), void (Base::*)(T*), OopClosureType* closure, T* p) {104// Sanity check105STATIC_ASSERT((!IsSame<OopClosureType, OopIterateClosure>::value));106closure->OopClosureType::do_oop(p);107}108109template <typename OopClosureType, typename T>110inline void Devirtualizer::do_oop(OopClosureType* closure, T* p) {111call_do_oop<T>(&OopClosureType::do_oop, &OopClosure::do_oop, closure, p);112}113114// Implementation of the non-virtual do_metadata dispatch.115116template <typename Receiver, typename Base, typename OopClosureType>117static typename EnableIf<IsSame<Receiver, Base>::value, bool>::type118call_do_metadata(bool (Receiver::*)(), bool (Base::*)(), OopClosureType* closure) {119return closure->do_metadata();120}121122template <typename Receiver, typename Base, typename OopClosureType>123static typename EnableIf<!IsSame<Receiver, Base>::value, bool>::type124call_do_metadata(bool (Receiver::*)(), bool (Base::*)(), OopClosureType* closure) {125return closure->OopClosureType::do_metadata();126}127128template <typename OopClosureType>129inline bool Devirtualizer::do_metadata(OopClosureType* closure) {130return call_do_metadata(&OopClosureType::do_metadata, &OopIterateClosure::do_metadata, closure);131}132133// Implementation of the non-virtual do_klass dispatch.134135template <typename Receiver, typename Base, typename OopClosureType>136static typename EnableIf<IsSame<Receiver, Base>::value, void>::type137call_do_klass(void (Receiver::*)(Klass*), void (Base::*)(Klass*), OopClosureType* closure, Klass* k) {138closure->do_klass(k);139}140141template <typename Receiver, typename Base, typename OopClosureType>142static typename EnableIf<!IsSame<Receiver, Base>::value, void>::type143call_do_klass(void (Receiver::*)(Klass*), void (Base::*)(Klass*), OopClosureType* closure, Klass* k) {144closure->OopClosureType::do_klass(k);145}146147template <typename OopClosureType>148inline void Devirtualizer::do_klass(OopClosureType* closure, Klass* k) {149call_do_klass(&OopClosureType::do_klass, &OopIterateClosure::do_klass, closure, k);150}151152// Implementation of the non-virtual do_cld dispatch.153154template <typename Receiver, typename Base, typename OopClosureType>155static typename EnableIf<IsSame<Receiver, Base>::value, void>::type156call_do_cld(void (Receiver::*)(ClassLoaderData*), void (Base::*)(ClassLoaderData*), OopClosureType* closure, ClassLoaderData* cld) {157closure->do_cld(cld);158}159160template <typename Receiver, typename Base, typename OopClosureType>161static typename EnableIf<!IsSame<Receiver, Base>::value, void>::type162call_do_cld(void (Receiver::*)(ClassLoaderData*), void (Base::*)(ClassLoaderData*), OopClosureType* closure, ClassLoaderData* cld) {163closure->OopClosureType::do_cld(cld);164}165166template <typename OopClosureType>167void Devirtualizer::do_cld(OopClosureType* closure, ClassLoaderData* cld) {168call_do_cld(&OopClosureType::do_cld, &OopIterateClosure::do_cld, closure, cld);169}170171// Dispatch table implementation for *Klass::oop_oop_iterate172//173// It allows for a single call to do a multi-dispatch to an optimized version174// of oop_oop_iterate that statically know all these types:175// - OopClosureType : static type give at call site176// - Klass* : dynamic to static type through Klass::id() -> table index177// - UseCompressedOops : dynamic to static value determined once178//179// when users call obj->oop_iterate(&cl).180//181// oopDesc::oop_iterate() calls OopOopIterateDispatch::function(klass)(cl, obj, klass),182// which dispatches to an optimized version of183// [Instance, ObjArry, etc]Klass::oop_oop_iterate(oop, OopClosureType)184//185// OopClosureType :186// If OopClosureType has an implementation of do_oop (and do_metadata et.al.),187// then the static type of OopClosureType will be used to allow inlining of188// do_oop (even though do_oop is virtual). Otherwise, a virtual call will be189// used when calling do_oop.190//191// Klass* :192// A table mapping from *Klass::ID to function is setup. This happens once193// when the program starts, when the static _table instance is initialized for194// the OopOopIterateDispatch specialized with the OopClosureType.195//196// UseCompressedOops :197// Initially the table is populated with an init function, and not the actual198// oop_oop_iterate function. This is done, so that the first time we dispatch199// through the init function we check what the value of UseCompressedOops200// became, and use that to determine if we should install an optimized201// narrowOop version or optimized oop version of oop_oop_iterate. The appropriate202// oop_oop_iterate function replaces the init function in the table, and203// succeeding calls will jump directly to oop_oop_iterate.204205206template <typename OopClosureType>207class OopOopIterateDispatch : public AllStatic {208private:209typedef void (*FunctionType)(OopClosureType*, oop, Klass*);210211class Table {212private:213template <typename KlassType, typename T>214static void oop_oop_iterate(OopClosureType* cl, oop obj, Klass* k) {215((KlassType*)k)->KlassType::template oop_oop_iterate<T>(obj, cl);216}217218template <typename KlassType>219static void init(OopClosureType* cl, oop obj, Klass* k) {220OopOopIterateDispatch<OopClosureType>::_table.set_resolve_function_and_execute<KlassType>(cl, obj, k);221}222223template <typename KlassType>224void set_init_function() {225_function[KlassType::ID] = &init<KlassType>;226}227228template <typename KlassType>229void set_resolve_function() {230// Size requirement to prevent word tearing231// when functions pointers are updated.232STATIC_ASSERT(sizeof(_function[0]) == sizeof(void*));233if (UseCompressedOops) {234_function[KlassType::ID] = &oop_oop_iterate<KlassType, narrowOop>;235} else {236_function[KlassType::ID] = &oop_oop_iterate<KlassType, oop>;237}238}239240template <typename KlassType>241void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k) {242set_resolve_function<KlassType>();243_function[KlassType::ID](cl, obj, k);244}245246public:247FunctionType _function[KLASS_ID_COUNT];248249Table(){250set_init_function<InstanceKlass>();251set_init_function<InstanceRefKlass>();252set_init_function<InstanceMirrorKlass>();253set_init_function<InstanceClassLoaderKlass>();254set_init_function<ObjArrayKlass>();255set_init_function<TypeArrayKlass>();256}257};258259static Table _table;260public:261262static FunctionType function(Klass* klass) {263return _table._function[klass->id()];264}265};266267template <typename OopClosureType>268typename OopOopIterateDispatch<OopClosureType>::Table OopOopIterateDispatch<OopClosureType>::_table;269270271template <typename OopClosureType>272class OopOopIterateBoundedDispatch {273private:274typedef void (*FunctionType)(OopClosureType*, oop, Klass*, MemRegion);275276class Table {277private:278template <typename KlassType, typename T>279static void oop_oop_iterate_bounded(OopClosureType* cl, oop obj, Klass* k, MemRegion mr) {280((KlassType*)k)->KlassType::template oop_oop_iterate_bounded<T>(obj, cl, mr);281}282283template <typename KlassType>284static void init(OopClosureType* cl, oop obj, Klass* k, MemRegion mr) {285OopOopIterateBoundedDispatch<OopClosureType>::_table.set_resolve_function_and_execute<KlassType>(cl, obj, k, mr);286}287288template <typename KlassType>289void set_init_function() {290_function[KlassType::ID] = &init<KlassType>;291}292293template <typename KlassType>294void set_resolve_function() {295if (UseCompressedOops) {296_function[KlassType::ID] = &oop_oop_iterate_bounded<KlassType, narrowOop>;297} else {298_function[KlassType::ID] = &oop_oop_iterate_bounded<KlassType, oop>;299}300}301302template <typename KlassType>303void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k, MemRegion mr) {304set_resolve_function<KlassType>();305_function[KlassType::ID](cl, obj, k, mr);306}307308public:309FunctionType _function[KLASS_ID_COUNT];310311Table(){312set_init_function<InstanceKlass>();313set_init_function<InstanceRefKlass>();314set_init_function<InstanceMirrorKlass>();315set_init_function<InstanceClassLoaderKlass>();316set_init_function<ObjArrayKlass>();317set_init_function<TypeArrayKlass>();318}319};320321static Table _table;322public:323324static FunctionType function(Klass* klass) {325return _table._function[klass->id()];326}327};328329template <typename OopClosureType>330typename OopOopIterateBoundedDispatch<OopClosureType>::Table OopOopIterateBoundedDispatch<OopClosureType>::_table;331332333template <typename OopClosureType>334class OopOopIterateBackwardsDispatch {335private:336typedef void (*FunctionType)(OopClosureType*, oop, Klass*);337338class Table {339private:340template <typename KlassType, typename T>341static void oop_oop_iterate_backwards(OopClosureType* cl, oop obj, Klass* k) {342((KlassType*)k)->KlassType::template oop_oop_iterate_reverse<T>(obj, cl);343}344345template <typename KlassType>346static void init(OopClosureType* cl, oop obj, Klass* k) {347OopOopIterateBackwardsDispatch<OopClosureType>::_table.set_resolve_function_and_execute<KlassType>(cl, obj, k);348}349350template <typename KlassType>351void set_init_function() {352_function[KlassType::ID] = &init<KlassType>;353}354355template <typename KlassType>356void set_resolve_function() {357if (UseCompressedOops) {358_function[KlassType::ID] = &oop_oop_iterate_backwards<KlassType, narrowOop>;359} else {360_function[KlassType::ID] = &oop_oop_iterate_backwards<KlassType, oop>;361}362}363364template <typename KlassType>365void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k) {366set_resolve_function<KlassType>();367_function[KlassType::ID](cl, obj, k);368}369370public:371FunctionType _function[KLASS_ID_COUNT];372373Table(){374set_init_function<InstanceKlass>();375set_init_function<InstanceRefKlass>();376set_init_function<InstanceMirrorKlass>();377set_init_function<InstanceClassLoaderKlass>();378set_init_function<ObjArrayKlass>();379set_init_function<TypeArrayKlass>();380}381};382383static Table _table;384public:385386static FunctionType function(Klass* klass) {387return _table._function[klass->id()];388}389};390391template <typename OopClosureType>392typename OopOopIterateBackwardsDispatch<OopClosureType>::Table OopOopIterateBackwardsDispatch<OopClosureType>::_table;393394395template <typename OopClosureType>396void OopIteratorClosureDispatch::oop_oop_iterate(OopClosureType* cl, oop obj, Klass* klass) {397OopOopIterateDispatch<OopClosureType>::function(klass)(cl, obj, klass);398}399400template <typename OopClosureType>401void OopIteratorClosureDispatch::oop_oop_iterate(OopClosureType* cl, oop obj, Klass* klass, MemRegion mr) {402OopOopIterateBoundedDispatch<OopClosureType>::function(klass)(cl, obj, klass, mr);403}404405template <typename OopClosureType>406void OopIteratorClosureDispatch::oop_oop_iterate_backwards(OopClosureType* cl, oop obj, Klass* klass) {407OopOopIterateBackwardsDispatch<OopClosureType>::function(klass)(cl, obj, klass);408}409410#endif // SHARE_MEMORY_ITERATOR_INLINE_HPP411412413