src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp

Mon, 19 Aug 2019 12:47:38 +0200

author
shade
date
Mon, 19 Aug 2019 12:47:38 +0200
changeset 9862
f162232da105
parent 9858
b985cbb00e68
child 9926
d20a5f399218
permissions
-rw-r--r--

8229873: 8229401 broke jdk8u-jfr-incubator
Reviewed-by: neugens

     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  */
    25 #ifndef SHARE_VM_JFR_RECORDER_CHECKPOINT_TYPES_JFRTYPESETUTILS_HPP
    26 #define SHARE_VM_JFR_RECORDER_CHECKPOINT_TYPES_JFRTYPESETUTILS_HPP
    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"
    35 // XXX is it correct?
    36 // external name (synthetic) for the primordial "bootstrap" class loader instance
    37 #define BOOTSTRAP_LOADER_NAME "<bootloader>" // XXX bootstrap
    38 #define BOOTSTRAP_LOADER_NAME_LEN 9
    40 // Composite callback/functor building block
    41 template <typename T, typename Func1, typename Func2>
    42 class CompositeFunctor {
    43  private:
    44   Func1* _f;
    45   Func2* _g;
    46  public:
    47   CompositeFunctor(Func1* f, Func2* g) : _f(f), _g(g) {
    48     assert(f != NULL, "invariant");
    49     assert(g != NULL, "invariant");
    50   }
    51   bool operator()(T const& value) {
    52     return (*_f)(value) && (*_g)(value);
    53   }
    54 };
    56 class JfrArtifactClosure {
    57  public:
    58   virtual void do_artifact(const void* artifact) = 0;
    59 };
    61 template <typename T, typename Callback>
    62 class JfrArtifactCallbackHost : public JfrArtifactClosure {
    63  private:
    64   Callback* _callback;
    65  public:
    66   JfrArtifactCallbackHost(Callback* callback) : _callback(callback) {}
    67   void do_artifact(const void* artifact) {
    68     (*_callback)(reinterpret_cast<T const&>(artifact));
    69   }
    70 };
    72 template <typename FieldSelector, typename Letter>
    73 class KlassToFieldEnvelope {
    74   Letter* _letter;
    75  public:
    76   KlassToFieldEnvelope(Letter* letter) : _letter(letter) {}
    77   bool operator()(const Klass* klass) {
    78     typename FieldSelector::TypePtr t = FieldSelector::select(klass);
    79     return t != NULL ? (*_letter)(t) : true;
    80   }
    81 };
    83 template <typename T>
    84 void tag_leakp_artifact(T const& value, bool class_unload) {
    85   assert(value != NULL, "invariant");
    86   if (class_unload) {
    87     SET_LEAKP_USED_THIS_EPOCH(value);
    88     assert(LEAKP_USED_THIS_EPOCH(value), "invariant");
    89   } else {
    90     SET_LEAKP_USED_PREV_EPOCH(value);
    91     assert(LEAKP_USED_PREV_EPOCH(value), "invariant");
    92   }
    93 }
    95 template <typename T>
    96 class LeakpClearArtifact {
    97   bool _class_unload;
    98  public:
    99   LeakpClearArtifact(bool class_unload) : _class_unload(class_unload) {}
   100   bool operator()(T const& value) {
   101     if (_class_unload) {
   102       if (LEAKP_USED_THIS_EPOCH(value)) {
   103         LEAKP_UNUSE_THIS_EPOCH(value);
   104       }
   105     } else {
   106       if (LEAKP_USED_PREV_EPOCH(value)) {
   107         LEAKP_UNUSE_PREV_EPOCH(value);
   108       }
   109     }
   110     return true;
   111   }
   112 };
   114 template <typename T>
   115 class ClearArtifact {
   116   bool _class_unload;
   117  public:
   118   ClearArtifact(bool class_unload) : _class_unload(class_unload) {}
   119   bool operator()(T const& value) {
   120     if (_class_unload) {
   121       if (LEAKP_USED_THIS_EPOCH(value)) {
   122         LEAKP_UNUSE_THIS_EPOCH(value);
   123       }
   124       if (USED_THIS_EPOCH(value)) {
   125         UNUSE_THIS_EPOCH(value);
   126       }
   127       if (METHOD_USED_THIS_EPOCH(value)) {
   128         UNUSE_METHOD_THIS_EPOCH(value);
   129       }
   130     } else {
   131       if (LEAKP_USED_PREV_EPOCH(value)) {
   132         LEAKP_UNUSE_PREV_EPOCH(value);
   133       }
   134       if (USED_PREV_EPOCH(value)) {
   135         UNUSE_PREV_EPOCH(value);
   136       }
   137       if (METHOD_USED_PREV_EPOCH(value)) {
   138         UNUSE_METHOD_PREV_EPOCH(value);
   139       }
   140     }
   141     return true;
   142   }
   143 };
   145 template <>
   146 class ClearArtifact<const Method*> {
   147   bool _class_unload;
   148  public:
   149   ClearArtifact(bool class_unload) : _class_unload(class_unload) {}
   150   bool operator()(const Method* method) {
   151     if (_class_unload) {
   152       if (METHOD_FLAG_USED_THIS_EPOCH(method)) {
   153         CLEAR_METHOD_FLAG_USED_THIS_EPOCH(method);
   154       }
   155     } else {
   156       if (METHOD_FLAG_USED_PREV_EPOCH(method)) {
   157         CLEAR_METHOD_FLAG_USED_PREV_EPOCH(method);
   158       }
   159     }
   160     return true;
   161   }
   162 };
   164 template <typename T>
   165 class LeakPredicate {
   166   bool _class_unload;
   167  public:
   168   LeakPredicate(bool class_unload) : _class_unload(class_unload) {}
   169   bool operator()(T const& value) {
   170     return _class_unload ? LEAKP_USED_THIS_EPOCH(value) : LEAKP_USED_PREV_EPOCH(value);
   171   }
   172 };
   174 template <typename T>
   175 class UsedPredicate {
   176   bool _class_unload;
   177  public:
   178   UsedPredicate(bool class_unload) : _class_unload(class_unload) {}
   179   bool operator()(T const& value) {
   180     return _class_unload ? USED_THIS_EPOCH(value) : USED_PREV_EPOCH(value);
   181   }
   182 };
   184 template <typename T, int compare(const T&, const T&)>
   185 class UniquePredicate {
   186  private:
   187   GrowableArray<T> _seen;
   188  public:
   189   UniquePredicate(bool) : _seen() {}
   190   bool operator()(T const& value) {
   191     bool not_unique;
   192     _seen.template find_sorted<T, compare>(value, not_unique);
   193     if (not_unique) {
   194       return false;
   195     }
   196     _seen.template insert_sorted<compare>(value);
   197     return true;
   198   }
   199 };
   201 class MethodFlagPredicate {
   202   bool _class_unload;
   203  public:
   204   MethodFlagPredicate(bool class_unload) : _class_unload(class_unload) {}
   205   bool operator()(const Method* method) {
   206     return _class_unload ? METHOD_FLAG_USED_THIS_EPOCH(method) : METHOD_FLAG_USED_PREV_EPOCH(method);
   207   }
   208 };
   210 template <bool leakp>
   211 class MethodUsedPredicate {
   212   bool _class_unload;
   213  public:
   214   MethodUsedPredicate(bool class_unload) : _class_unload(class_unload) {}
   215   bool operator()(const Klass* klass) {
   216     assert(ANY_USED(klass), "invariant");
   217     if (_class_unload) {
   218       return leakp ? LEAKP_METHOD_USED_THIS_EPOCH(klass) : METHOD_USED_THIS_EPOCH(klass);
   219     }
   220     return leakp ? LEAKP_METHOD_USED_PREV_EPOCH(klass) : METHOD_USED_PREV_EPOCH(klass);
   221   }
   222 };
   224 class JfrSymbolId : public JfrCHeapObj {
   225   template <typename, typename, template<typename, typename> class, typename, size_t>
   226   friend class HashTableHost;
   227   typedef HashTableHost<const Symbol*, traceid, Entry, JfrSymbolId> SymbolTable;
   228   typedef HashTableHost<const char*, traceid, Entry, JfrSymbolId> CStringTable;
   229  public:
   230   typedef SymbolTable::HashEntry SymbolEntry;
   231   typedef CStringTable::HashEntry CStringEntry;
   232  private:
   233   SymbolTable* _sym_table;
   234   CStringTable* _cstring_table;
   235   traceid _symbol_id_counter;
   237   // hashtable(s) callbacks
   238   void assign_id(SymbolEntry* entry);
   239   bool equals(const Symbol* query, uintptr_t hash, const SymbolEntry* entry);
   240   void assign_id(CStringEntry* entry);
   241   bool equals(const char* query, uintptr_t hash, const CStringEntry* entry);
   243  public:
   244   static bool is_anonymous_klass(const Klass* k);
   245   static const char* create_anonymous_klass_symbol(const InstanceKlass* ik, uintptr_t& hashcode);
   246   static uintptr_t anonymous_klass_name_hash_code(const InstanceKlass* ik);
   247   static uintptr_t regular_klass_name_hash_code(const Klass* k);
   249   JfrSymbolId();
   250   ~JfrSymbolId();
   252   void initialize();
   253   void clear();
   255   traceid mark_anonymous_klass_name(const Klass* k);
   256   traceid mark(const Symbol* sym, uintptr_t hash);
   257   traceid mark(const Klass* k);
   258   traceid mark(const Symbol* symbol);
   259   traceid mark(const char* str, uintptr_t hash);
   261   const SymbolEntry* map_symbol(const Symbol* symbol) const;
   262   const SymbolEntry* map_symbol(uintptr_t hash) const;
   263   const CStringEntry* map_cstring(uintptr_t hash) const;
   265   template <typename T>
   266   void symbol(T& functor, const Klass* k) {
   267     if (is_anonymous_klass(k)) {
   268       return;
   269     }
   270     functor(map_symbol(regular_klass_name_hash_code(k)));
   271   }
   273   template <typename T>
   274   void symbol(T& functor, const Method* method) {
   275     assert(method != NULL, "invariant");
   276     functor(map_symbol((uintptr_t)method->name()->identity_hash()));
   277     functor(map_symbol((uintptr_t)method->signature()->identity_hash()));
   278   }
   280   template <typename T>
   281   void cstring(T& functor, const Klass* k) {
   282     if (!is_anonymous_klass(k)) {
   283       return;
   284     }
   285     functor(map_cstring(anonymous_klass_name_hash_code((const InstanceKlass*)k)));
   286   }
   288   template <typename T>
   289   void iterate_symbols(T& functor) {
   290     _sym_table->iterate_entry(functor);
   291   }
   293   template <typename T>
   294   void iterate_cstrings(T& functor) {
   295     _cstring_table->iterate_entry(functor);
   296   }
   298   bool has_entries() const { return has_symbol_entries() || has_cstring_entries(); }
   299   bool has_symbol_entries() const { return _sym_table->has_entries(); }
   300   bool has_cstring_entries() const { return _cstring_table->has_entries(); }
   301 };
   303 /**
   304  * When processing a set of artifacts, there will be a need
   305  * to track transitive dependencies originating with each artifact.
   306  * These might or might not be explicitly "tagged" at that point.
   307  * With the introduction of "epochs" to allow for concurrent tagging,
   308  * we attempt to avoid "tagging" an artifact to indicate its use in a
   309  * previous epoch. This is mainly to reduce the risk for data races.
   310  * Instead, JfrArtifactSet is used to track transitive dependencies
   311  * during the write process itself.
   312  *
   313  * It can also provide opportunities for caching, as the ideal should
   314  * be to reduce the amount of iterations neccessary for locating artifacts
   315  * in the respective VM subsystems.
   316  */
   317 class JfrArtifactSet : public JfrCHeapObj {
   318  private:
   319   JfrSymbolId* _symbol_id;
   320   GrowableArray<const Klass*>* _klass_list;
   321   bool _class_unload;
   323  public:
   324   JfrArtifactSet(bool class_unload);
   325   ~JfrArtifactSet();
   327   // caller needs ResourceMark
   328   void initialize(bool class_unload);
   329   void clear();
   331   traceid mark(const Symbol* sym, uintptr_t hash);
   332   traceid mark(const Klass* klass);
   333   traceid mark(const Symbol* symbol);
   334   traceid mark(const char* const str, uintptr_t hash);
   335   traceid mark_anonymous_klass_name(const Klass* klass);
   337   const JfrSymbolId::SymbolEntry* map_symbol(const Symbol* symbol) const;
   338   const JfrSymbolId::SymbolEntry* map_symbol(uintptr_t hash) const;
   339   const JfrSymbolId::CStringEntry* map_cstring(uintptr_t hash) const;
   341   bool has_klass_entries() const;
   342   int entries() const;
   343   void register_klass(const Klass* k);
   345   template <typename Functor>
   346   void iterate_klasses(Functor& functor) const {
   347     for (int i = 0; i < _klass_list->length(); ++i) {
   348       if (!functor(_klass_list->at(i))) {
   349         break;
   350       }
   351     }
   352   }
   354   template <typename T>
   355   void iterate_symbols(T& functor) {
   356     _symbol_id->iterate_symbols(functor);
   357   }
   359   template <typename T>
   360   void iterate_cstrings(T& functor) {
   361     _symbol_id->iterate_cstrings(functor);
   362   }
   363 };
   365 class KlassArtifactRegistrator {
   366  private:
   367   JfrArtifactSet* _artifacts;
   368  public:
   369   KlassArtifactRegistrator(JfrArtifactSet* artifacts) :
   370     _artifacts(artifacts) {
   371     assert(_artifacts != NULL, "invariant");
   372   }
   374   bool operator()(const Klass* klass) {
   375     assert(klass != NULL, "invariant");
   376     _artifacts->register_klass(klass);
   377     return true;
   378   }
   379 };
   381 #endif // SHARE_VM_JFR_RECORDER_CHECKPOINT_TYPES_JFRTYPESETUTILS_HPP

mercurial