duke@435: /* duke@435: * Copyright 2001-2006 Sun Microsystems, Inc. All Rights Reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: // The following OopClosure types get specialized versions of duke@435: // "oop_oop_iterate" that invoke the closures' do_oop methods duke@435: // non-virtually, using a mechanism defined in this file. Extend these duke@435: // macros in the obvious way to add specializations for new closures. duke@435: duke@435: // Forward declarations. duke@435: class OopClosure; duke@435: class OopsInGenClosure; duke@435: // DefNew duke@435: class ScanClosure; duke@435: class FastScanClosure; duke@435: class FilteringClosure; duke@435: // ParNew duke@435: class ParScanWithBarrierClosure; duke@435: class ParScanWithoutBarrierClosure; duke@435: // CMS duke@435: class MarkRefsIntoAndScanClosure; duke@435: class Par_MarkRefsIntoAndScanClosure; duke@435: class PushAndMarkClosure; duke@435: class Par_PushAndMarkClosure; duke@435: class PushOrMarkClosure; duke@435: class Par_PushOrMarkClosure; duke@435: class CMSKeepAliveClosure; duke@435: class CMSInnerParMarkAndPushClosure; duke@435: duke@435: // This macro applies an argument macro to all OopClosures for which we duke@435: // want specialized bodies of "oop_oop_iterate". The arguments to "f" are: duke@435: // "f(closureType, non_virtual)" duke@435: // where "closureType" is the name of the particular subclass of OopClosure, duke@435: // and "non_virtual" will be the string "_nv" if the closure type should duke@435: // have its "do_oop" method invoked non-virtually, or else the duke@435: // string "_v". ("OopClosure" itself will be the only class in the latter duke@435: // category.) duke@435: duke@435: // This is split into several because of a Visual C++ 6.0 compiler bug duke@435: // where very long macros cause the compiler to crash duke@435: ysr@777: // Some other heap might define further specialized closures. ysr@777: #ifndef FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES ysr@777: #define FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES(f) \ ysr@777: /* None */ ysr@777: #endif ysr@777: duke@435: #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_S(f) \ duke@435: f(ScanClosure,_nv) \ duke@435: f(FastScanClosure,_nv) \ duke@435: f(FilteringClosure,_nv) duke@435: duke@435: #ifndef SERIALGC duke@435: #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f) \ duke@435: f(ParScanWithBarrierClosure,_nv) \ duke@435: f(ParScanWithoutBarrierClosure,_nv) duke@435: #else // SERIALGC duke@435: #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f) duke@435: #endif // SERIALGC duke@435: duke@435: #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(f) \ duke@435: SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_S(f) \ duke@435: SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f) duke@435: duke@435: #ifndef SERIALGC ysr@777: #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) \ duke@435: f(MarkRefsIntoAndScanClosure,_nv) \ duke@435: f(Par_MarkRefsIntoAndScanClosure,_nv) \ duke@435: f(PushAndMarkClosure,_nv) \ duke@435: f(Par_PushAndMarkClosure,_nv) \ duke@435: f(PushOrMarkClosure,_nv) \ duke@435: f(Par_PushOrMarkClosure,_nv) \ duke@435: f(CMSKeepAliveClosure,_nv) \ ysr@777: f(CMSInnerParMarkAndPushClosure,_nv) \ ysr@777: FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES(f) duke@435: #else // SERIALGC ysr@777: #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) duke@435: #endif // SERIALGC duke@435: ysr@777: duke@435: // We separate these out, because sometime the general one has duke@435: // a different definition from the specialized ones, and sometimes it duke@435: // doesn't. duke@435: duke@435: #define ALL_OOP_OOP_ITERATE_CLOSURES_1(f) \ duke@435: f(OopClosure,_v) \ duke@435: SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(f) duke@435: ysr@777: #define ALL_OOP_OOP_ITERATE_CLOSURES_2(f) \ ysr@777: SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) duke@435: duke@435: #ifndef SERIALGC duke@435: // This macro applies an argument macro to all OopClosures for which we duke@435: // want specialized bodies of a family of methods related to duke@435: // "par_oop_iterate". The arguments to f are the same as above. duke@435: // The "root_class" is the most general class to define; this may be duke@435: // "OopClosure" in some applications and "OopsInGenClosure" in others. duke@435: duke@435: #define SPECIALIZED_PAR_OOP_ITERATE_CLOSURES(f) \ duke@435: f(MarkRefsIntoAndScanClosure,_nv) \ duke@435: f(PushAndMarkClosure,_nv) \ duke@435: f(Par_MarkRefsIntoAndScanClosure,_nv) \ duke@435: f(Par_PushAndMarkClosure,_nv) duke@435: duke@435: #define ALL_PAR_OOP_ITERATE_CLOSURES(f) \ duke@435: f(OopClosure,_v) \ duke@435: SPECIALIZED_PAR_OOP_ITERATE_CLOSURES(f) duke@435: #endif // SERIALGC duke@435: duke@435: // This macro applies an argument macro to all OopClosures for which we duke@435: // want specialized bodies of a family of methods related to duke@435: // "oops_since_save_marks_do". The arguments to f are the same as above. duke@435: // The "root_class" is the most general class to define; this may be duke@435: // "OopClosure" in some applications and "OopsInGenClosure" in others. duke@435: ysr@777: ysr@777: // Some other heap might define further specialized closures. ysr@777: #ifndef FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES ysr@777: #define FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(f) \ ysr@777: /* None */ ysr@777: #endif ysr@777: duke@435: #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_S(f) \ duke@435: f(ScanClosure,_nv) \ duke@435: f(FastScanClosure,_nv) duke@435: duke@435: #ifndef SERIALGC duke@435: #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f) \ duke@435: f(ParScanWithBarrierClosure,_nv) \ ysr@777: f(ParScanWithoutBarrierClosure,_nv) \ ysr@777: FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(f) duke@435: #else // SERIALGC duke@435: #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f) duke@435: #endif // SERIALGC duke@435: duke@435: #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(f) \ duke@435: SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_S(f) \ duke@435: SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f) duke@435: duke@435: #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(f) \ duke@435: SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(f) duke@435: duke@435: // We separate these out, because sometime the general one has duke@435: // a different definition from the specialized ones, and sometimes it duke@435: // doesn't. duke@435: // NOTE: One of the valid criticisms of this duke@435: // specialize-oop_oop_iterate-for-specific-closures idiom is that it is duke@435: // easy to have a silent performance bug: if you fail to de-virtualize, duke@435: // things still work, just slower. The "SpecializationStats" mode is duke@435: // intended to at least make such a failure easy to detect. duke@435: // *Not* using the ALL_SINCE_SAVE_MARKS_CLOSURES(f) macro defined duke@435: // below means that *only* closures for which oop_oop_iterate specializations duke@435: // exist above may be applied to "oops_since_save_marks". That is, duke@435: // this form of the performance bug is caught statically. When you add duke@435: // a definition for the general type, this property goes away. duke@435: // Make sure you test with SpecializationStats to find such bugs duke@435: // when introducing a new closure where you don't want virtual dispatch. duke@435: duke@435: #define ALL_SINCE_SAVE_MARKS_CLOSURES(f) \ duke@435: f(OopsInGenClosure,_v) \ duke@435: SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(f) duke@435: duke@435: // For keeping stats on effectiveness. duke@435: #define ENABLE_SPECIALIZATION_STATS 0 duke@435: duke@435: duke@435: class SpecializationStats { duke@435: public: duke@435: enum Kind { duke@435: ik, // instanceKlass duke@435: irk, // instanceRefKlass duke@435: oa, // objArrayKlass duke@435: NUM_Kinds duke@435: }; duke@435: duke@435: #if ENABLE_SPECIALIZATION_STATS duke@435: private: ysr@777: static bool _init; ysr@777: static bool _wrapped; ysr@777: static jint _numCallsAll; duke@435: ysr@777: static jint _numCallsTotal[NUM_Kinds]; ysr@777: static jint _numCalls_nv[NUM_Kinds]; duke@435: ysr@777: static jint _numDoOopCallsTotal[NUM_Kinds]; ysr@777: static jint _numDoOopCalls_nv[NUM_Kinds]; duke@435: public: duke@435: #endif duke@435: static void clear() PRODUCT_RETURN; duke@435: duke@435: static inline void record_call() PRODUCT_RETURN; duke@435: static inline void record_iterate_call_v(Kind k) PRODUCT_RETURN; duke@435: static inline void record_iterate_call_nv(Kind k) PRODUCT_RETURN; duke@435: static inline void record_do_oop_call_v(Kind k) PRODUCT_RETURN; duke@435: static inline void record_do_oop_call_nv(Kind k) PRODUCT_RETURN; duke@435: duke@435: static void print() PRODUCT_RETURN; duke@435: }; duke@435: duke@435: #ifndef PRODUCT duke@435: #if ENABLE_SPECIALIZATION_STATS duke@435: duke@435: inline void SpecializationStats::record_call() { ysr@777: Atomic::inc(&_numCallsAll); duke@435: } duke@435: inline void SpecializationStats::record_iterate_call_v(Kind k) { ysr@777: Atomic::inc(&_numCallsTotal[k]); duke@435: } duke@435: inline void SpecializationStats::record_iterate_call_nv(Kind k) { ysr@777: Atomic::inc(&_numCallsTotal[k]); ysr@777: Atomic::inc(&_numCalls_nv[k]); duke@435: } duke@435: duke@435: inline void SpecializationStats::record_do_oop_call_v(Kind k) { ysr@777: Atomic::inc(&_numDoOopCallsTotal[k]); duke@435: } duke@435: inline void SpecializationStats::record_do_oop_call_nv(Kind k) { ysr@777: Atomic::inc(&_numDoOopCallsTotal[k]); ysr@777: Atomic::inc(&_numDoOopCalls_nv[k]); duke@435: } duke@435: duke@435: #else // !ENABLE_SPECIALIZATION_STATS duke@435: duke@435: inline void SpecializationStats::record_call() {} duke@435: inline void SpecializationStats::record_iterate_call_v(Kind k) {} duke@435: inline void SpecializationStats::record_iterate_call_nv(Kind k) {} duke@435: inline void SpecializationStats::record_do_oop_call_v(Kind k) {} duke@435: inline void SpecializationStats::record_do_oop_call_nv(Kind k) {} duke@435: inline void SpecializationStats::clear() {} duke@435: inline void SpecializationStats::print() {} duke@435: duke@435: #endif // ENABLE_SPECIALIZATION_STATS duke@435: #endif // !PRODUCT