src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp
changeset 50113 caf115bb98ad
child 50634 c349d409262a
equal deleted inserted replaced
50112:7a2a740815b7 50113:caf115bb98ad
       
     1 /*
       
     2  * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #ifndef SHARE_VM_JFR_RECORDER_CHECKPOINT_TYPES_JFRTYPESETUTILS_HPP
       
    26 #define SHARE_VM_JFR_RECORDER_CHECKPOINT_TYPES_JFRTYPESETUTILS_HPP
       
    27 
       
    28 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
       
    29 #include "jfr/utilities/jfrAllocation.hpp"
       
    30 #include "jfr/utilities/jfrHashtable.hpp"
       
    31 #include "oops/klass.hpp"
       
    32 #include "oops/method.hpp"
       
    33 #include "utilities/growableArray.hpp"
       
    34 
       
    35 // Composite callback/functor building block
       
    36 template <typename T, typename Func1, typename Func2>
       
    37 class CompositeFunctor {
       
    38  private:
       
    39   Func1* _f;
       
    40   Func2* _g;
       
    41  public:
       
    42   CompositeFunctor(Func1* f, Func2* g) : _f(f), _g(g) {
       
    43     assert(f != NULL, "invariant");
       
    44     assert(g != NULL, "invariant");
       
    45   }
       
    46   bool operator()(T const& value) {
       
    47     return (*_f)(value) && (*_g)(value);
       
    48   }
       
    49 };
       
    50 
       
    51 class JfrArtifactClosure {
       
    52  public:
       
    53   virtual void do_artifact(const void* artifact) = 0;
       
    54 };
       
    55 
       
    56 template <typename T, typename Callback>
       
    57 class JfrArtifactCallbackHost : public JfrArtifactClosure {
       
    58  private:
       
    59   Callback* _callback;
       
    60  public:
       
    61   JfrArtifactCallbackHost(Callback* callback) : _callback(callback) {}
       
    62   void do_artifact(const void* artifact) {
       
    63     (*_callback)(reinterpret_cast<T const&>(artifact));
       
    64   }
       
    65 };
       
    66 
       
    67 template <typename FieldSelector, typename Letter>
       
    68 class KlassToFieldEnvelope {
       
    69   Letter* _letter;
       
    70  public:
       
    71   KlassToFieldEnvelope(Letter* letter) : _letter(letter) {}
       
    72   bool operator()(const Klass* klass) {
       
    73     typename FieldSelector::TypePtr t = FieldSelector::select(klass);
       
    74     return t != NULL ? (*_letter)(t) : true;
       
    75   }
       
    76 };
       
    77 
       
    78 template <typename T>
       
    79 void tag_leakp_artifact(T const& value, bool class_unload) {
       
    80   assert(value != NULL, "invariant");
       
    81   if (class_unload) {
       
    82     SET_LEAKP_USED_THIS_EPOCH(value);
       
    83     assert(LEAKP_USED_THIS_EPOCH(value), "invariant");
       
    84   } else {
       
    85     SET_LEAKP_USED_PREV_EPOCH(value);
       
    86     assert(LEAKP_USED_PREV_EPOCH(value), "invariant");
       
    87   }
       
    88 }
       
    89 
       
    90 template <typename T>
       
    91 class LeakpClearArtifact {
       
    92   bool _class_unload;
       
    93  public:
       
    94   LeakpClearArtifact(bool class_unload) : _class_unload(class_unload) {}
       
    95   bool operator()(T const& value) {
       
    96     if (_class_unload) {
       
    97       if (LEAKP_USED_THIS_EPOCH(value)) {
       
    98         LEAKP_UNUSE_THIS_EPOCH(value);
       
    99       }
       
   100     } else {
       
   101       if (LEAKP_USED_PREV_EPOCH(value)) {
       
   102         LEAKP_UNUSE_PREV_EPOCH(value);
       
   103       }
       
   104     }
       
   105     return true;
       
   106   }
       
   107 };
       
   108 
       
   109 template <typename T>
       
   110 class ClearArtifact {
       
   111   bool _class_unload;
       
   112  public:
       
   113   ClearArtifact(bool class_unload) : _class_unload(class_unload) {}
       
   114   bool operator()(T const& value) {
       
   115     if (_class_unload) {
       
   116       if (LEAKP_USED_THIS_EPOCH(value)) {
       
   117         LEAKP_UNUSE_THIS_EPOCH(value);
       
   118       }
       
   119       if (USED_THIS_EPOCH(value)) {
       
   120         UNUSE_THIS_EPOCH(value);
       
   121       }
       
   122       if (METHOD_USED_THIS_EPOCH(value)) {
       
   123         UNUSE_METHOD_THIS_EPOCH(value);
       
   124       }
       
   125     } else {
       
   126       if (LEAKP_USED_PREV_EPOCH(value)) {
       
   127         LEAKP_UNUSE_PREV_EPOCH(value);
       
   128       }
       
   129       if (USED_PREV_EPOCH(value)) {
       
   130         UNUSE_PREV_EPOCH(value);
       
   131       }
       
   132       if (METHOD_USED_PREV_EPOCH(value)) {
       
   133         UNUSE_METHOD_PREV_EPOCH(value);
       
   134       }
       
   135     }
       
   136     return true;
       
   137   }
       
   138 };
       
   139 
       
   140 template <>
       
   141 class ClearArtifact<const Method*> {
       
   142   bool _class_unload;
       
   143  public:
       
   144   ClearArtifact(bool class_unload) : _class_unload(class_unload) {}
       
   145   bool operator()(const Method* method) {
       
   146     if (_class_unload) {
       
   147       if (METHOD_FLAG_USED_THIS_EPOCH(method)) {
       
   148         CLEAR_METHOD_FLAG_USED_THIS_EPOCH(method);
       
   149       }
       
   150     } else {
       
   151       if (METHOD_FLAG_USED_PREV_EPOCH(method)) {
       
   152         CLEAR_METHOD_FLAG_USED_PREV_EPOCH(method);
       
   153       }
       
   154     }
       
   155     return true;
       
   156   }
       
   157 };
       
   158 
       
   159 template <typename T>
       
   160 class LeakPredicate {
       
   161   bool _class_unload;
       
   162  public:
       
   163   LeakPredicate(bool class_unload) : _class_unload(class_unload) {}
       
   164   bool operator()(T const& value) {
       
   165     return _class_unload ? LEAKP_USED_THIS_EPOCH(value) : LEAKP_USED_PREV_EPOCH(value);
       
   166   }
       
   167 };
       
   168 
       
   169 template <typename T>
       
   170 class UsedPredicate {
       
   171   bool _class_unload;
       
   172  public:
       
   173   UsedPredicate(bool class_unload) : _class_unload(class_unload) {}
       
   174   bool operator()(T const& value) {
       
   175     return _class_unload ? USED_THIS_EPOCH(value) : USED_PREV_EPOCH(value);
       
   176   }
       
   177 };
       
   178 
       
   179 template <typename T, int compare(const T&, const T&)>
       
   180 class UniquePredicate {
       
   181  private:
       
   182   GrowableArray<T> _seen;
       
   183  public:
       
   184   UniquePredicate(bool) : _seen() {}
       
   185   bool operator()(T const& value) {
       
   186     bool not_unique;
       
   187     _seen.template find_sorted<T, compare>(value, not_unique);
       
   188     if (not_unique) {
       
   189       return false;
       
   190     }
       
   191     _seen.template insert_sorted<compare>(value);
       
   192     return true;
       
   193   }
       
   194 };
       
   195 
       
   196 class MethodFlagPredicate {
       
   197   bool _class_unload;
       
   198  public:
       
   199   MethodFlagPredicate(bool class_unload) : _class_unload(class_unload) {}
       
   200   bool operator()(const Method* method) {
       
   201     return _class_unload ? METHOD_FLAG_USED_THIS_EPOCH(method) : METHOD_FLAG_USED_PREV_EPOCH(method);
       
   202   }
       
   203 };
       
   204 
       
   205 template <bool leakp>
       
   206 class MethodUsedPredicate {
       
   207   bool _class_unload;
       
   208  public:
       
   209   MethodUsedPredicate(bool class_unload) : _class_unload(class_unload) {}
       
   210   bool operator()(const Klass* klass) {
       
   211     assert(ANY_USED(klass), "invariant");
       
   212     if (_class_unload) {
       
   213       return leakp ? LEAKP_METHOD_USED_THIS_EPOCH(klass) : METHOD_USED_THIS_EPOCH(klass);
       
   214     }
       
   215     return leakp ? LEAKP_METHOD_USED_PREV_EPOCH(klass) : METHOD_USED_PREV_EPOCH(klass);
       
   216   }
       
   217 };
       
   218 
       
   219 class JfrSymbolId : public JfrCHeapObj {
       
   220   template <typename, typename, template<typename, typename> class, typename, size_t>
       
   221   friend class HashTableHost;
       
   222   typedef HashTableHost<const Symbol*, traceid, Entry, JfrSymbolId> SymbolTable;
       
   223   typedef HashTableHost<const char*, traceid, Entry, JfrSymbolId> CStringTable;
       
   224  public:
       
   225   typedef SymbolTable::HashEntry SymbolEntry;
       
   226   typedef CStringTable::HashEntry CStringEntry;
       
   227  private:
       
   228   SymbolTable* _sym_table;
       
   229   CStringTable* _cstring_table;
       
   230   traceid _symbol_id_counter;
       
   231 
       
   232   // hashtable(s) callbacks
       
   233   void assign_id(SymbolEntry* entry);
       
   234   bool equals(const Symbol* query, uintptr_t hash, const SymbolEntry* entry);
       
   235   void assign_id(CStringEntry* entry);
       
   236   bool equals(const char* query, uintptr_t hash, const CStringEntry* entry);
       
   237 
       
   238  public:
       
   239   static bool is_anonymous_klass(const Klass* k);
       
   240   static const char* create_anonymous_klass_symbol(const InstanceKlass* ik, uintptr_t& hashcode);
       
   241   static uintptr_t anonymous_klass_name_hash_code(const InstanceKlass* ik);
       
   242   static uintptr_t regular_klass_name_hash_code(const Klass* k);
       
   243 
       
   244   JfrSymbolId();
       
   245   ~JfrSymbolId();
       
   246 
       
   247   void initialize();
       
   248   void clear();
       
   249 
       
   250   traceid mark_anonymous_klass_name(const Klass* k);
       
   251   traceid mark(const Symbol* sym, uintptr_t hash);
       
   252   traceid mark(const Klass* k);
       
   253   traceid mark(const Symbol* symbol);
       
   254   traceid mark(const char* str, uintptr_t hash);
       
   255 
       
   256   const SymbolEntry* map_symbol(const Symbol* symbol) const;
       
   257   const SymbolEntry* map_symbol(uintptr_t hash) const;
       
   258   const CStringEntry* map_cstring(uintptr_t hash) const;
       
   259 
       
   260   template <typename T>
       
   261   void symbol(T& functor, const Klass* k) {
       
   262     if (is_anonymous_klass(k)) {
       
   263       return;
       
   264     }
       
   265     functor(map_symbol(regular_klass_name_hash_code(k)));
       
   266   }
       
   267 
       
   268   template <typename T>
       
   269   void symbol(T& functor, const Method* method) {
       
   270     assert(method != NULL, "invariant");
       
   271     functor(map_symbol((uintptr_t)method->name()->identity_hash()));
       
   272     functor(map_symbol((uintptr_t)method->signature()->identity_hash()));
       
   273   }
       
   274 
       
   275   template <typename T>
       
   276   void cstring(T& functor, const Klass* k) {
       
   277     if (!is_anonymous_klass(k)) {
       
   278       return;
       
   279     }
       
   280     functor(map_cstring(anonymous_klass_name_hash_code((const InstanceKlass*)k)));
       
   281   }
       
   282 
       
   283   template <typename T>
       
   284   void iterate_symbols(T& functor) {
       
   285     _sym_table->iterate_entry(functor);
       
   286   }
       
   287 
       
   288   template <typename T>
       
   289   void iterate_cstrings(T& functor) {
       
   290     _cstring_table->iterate_entry(functor);
       
   291   }
       
   292 
       
   293   bool has_entries() const { return has_symbol_entries() || has_cstring_entries(); }
       
   294   bool has_symbol_entries() const { return _sym_table->has_entries(); }
       
   295   bool has_cstring_entries() const { return _cstring_table->has_entries(); }
       
   296 };
       
   297 
       
   298 // external name (synthetic) for the primordial "boot" class loader instance
       
   299 const char* const boot_class_loader_name = "boot";
       
   300 
       
   301 /**
       
   302  * When processing a set of artifacts, there will be a need
       
   303  * to track transitive dependencies originating with each artifact.
       
   304  * These might or might not be explicitly "tagged" at that point.
       
   305  * With the introduction of "epochs" to allow for concurrent tagging,
       
   306  * we attempt to avoid "tagging" an artifact to indicate its use in a
       
   307  * previous epoch. This is mainly to reduce the risk for data races.
       
   308  * Instead, JfrArtifactSet is used to track transitive dependencies
       
   309  * during the write process itself.
       
   310  *
       
   311  * It can also provide opportunities for caching, as the ideal should
       
   312  * be to reduce the amount of iterations neccessary for locating artifacts
       
   313  * in the respective VM subsystems.
       
   314  */
       
   315 class JfrArtifactSet : public JfrCHeapObj {
       
   316  private:
       
   317   JfrSymbolId* _symbol_id;
       
   318   GrowableArray<const Klass*>* _klass_list;
       
   319   bool _class_unload;
       
   320 
       
   321  public:
       
   322   JfrArtifactSet(bool class_unload);
       
   323   ~JfrArtifactSet();
       
   324 
       
   325   // caller needs ResourceMark
       
   326   void initialize(bool class_unload);
       
   327   void clear();
       
   328 
       
   329   traceid mark(const Symbol* sym, uintptr_t hash);
       
   330   traceid mark(const Klass* klass);
       
   331   traceid mark(const Symbol* symbol);
       
   332   traceid mark(const char* const str, uintptr_t hash);
       
   333   traceid mark_anonymous_klass_name(const Klass* klass);
       
   334 
       
   335   const JfrSymbolId::SymbolEntry* map_symbol(const Symbol* symbol) const;
       
   336   const JfrSymbolId::SymbolEntry* map_symbol(uintptr_t hash) const;
       
   337   const JfrSymbolId::CStringEntry* map_cstring(uintptr_t hash) const;
       
   338 
       
   339   bool has_klass_entries() const;
       
   340   int entries() const;
       
   341   void register_klass(const Klass* k);
       
   342 
       
   343   template <typename Functor>
       
   344   void iterate_klasses(Functor& functor) const {
       
   345     for (int i = 0; i < _klass_list->length(); ++i) {
       
   346       if (!functor(_klass_list->at(i))) {
       
   347         break;
       
   348       }
       
   349     }
       
   350   }
       
   351 
       
   352   template <typename T>
       
   353   void iterate_symbols(T& functor) {
       
   354     _symbol_id->iterate_symbols(functor);
       
   355   }
       
   356 
       
   357   template <typename T>
       
   358   void iterate_cstrings(T& functor) {
       
   359     _symbol_id->iterate_cstrings(functor);
       
   360   }
       
   361 };
       
   362 
       
   363 class KlassArtifactRegistrator {
       
   364  private:
       
   365   JfrArtifactSet* _artifacts;
       
   366  public:
       
   367   KlassArtifactRegistrator(JfrArtifactSet* artifacts) :
       
   368     _artifacts(artifacts) {
       
   369     assert(_artifacts != NULL, "invariant");
       
   370   }
       
   371 
       
   372   bool operator()(const Klass* klass) {
       
   373     assert(klass != NULL, "invariant");
       
   374     _artifacts->register_klass(klass);
       
   375     return true;
       
   376   }
       
   377 };
       
   378 
       
   379 #endif // SHARE_VM_JFR_RECORDER_CHECKPOINT_TYPES_JFRTYPESETUTILS_HPP