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 // 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
  39 
  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 };
  55 
  56 class JfrArtifactClosure {
  57  public:
  58   virtual void do_artifact(const void* artifact) = 0;
  59 };
  60 
  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 };
  71 
  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 };
  82 
  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 }
  94 
  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 };
 113 
 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 };
 144 
 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 };
 163 
 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 };
 173 
 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 };
 183 
 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 };
 200 
 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 };
 209 
 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 };
 223 
 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;
 236 
 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);
 242 
 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);
 248 
 249   JfrSymbolId();
 250   ~JfrSymbolId();
 251 
 252   void initialize();
 253   void clear();
 254 
 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);
 260 
 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;
 264 
 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   }
 272 
 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   }
 279 
 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   }
 287 
 288   template <typename T>
 289   void iterate_symbols(T& functor) {
 290     _sym_table->iterate_entry(functor);
 291   }
 292 
 293   template <typename T>
 294   void iterate_cstrings(T& functor) {
 295     _cstring_table->iterate_entry(functor);
 296   }
 297 
 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 };
 302 
 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;
 322 
 323  public:
 324   JfrArtifactSet(bool class_unload);
 325   ~JfrArtifactSet();
 326 
 327   // caller needs ResourceMark
 328   void initialize(bool class_unload);
 329   void clear();
 330 
 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);
 336 
 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;
 340 
 341   bool has_klass_entries() const;
 342   int entries() const;
 343   void register_klass(const Klass* k);
 344 
 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   }
 353 
 354   template <typename T>
 355   void iterate_symbols(T& functor) {
 356     _symbol_id->iterate_symbols(functor);
 357   }
 358 
 359   template <typename T>
 360   void iterate_cstrings(T& functor) {
 361     _symbol_id->iterate_cstrings(functor);
 362   }
 363 };
 364 
 365 class KlassArtifactRegistrator {
 366  private:
 367   JfrArtifactSet* _artifacts;
 368  public:
 369   KlassArtifactRegistrator(JfrArtifactSet* artifacts) :
 370     _artifacts(artifacts) {
 371     assert(_artifacts != NULL, "invariant");
 372   }
 373 
 374   bool operator()(const Klass* klass) {
 375     assert(klass != NULL, "invariant");
 376     _artifacts->register_klass(klass);
 377     return true;
 378   }
 379 };
 380 
 381 #endif // SHARE_VM_JFR_RECORDER_CHECKPOINT_TYPES_JFRTYPESETUTILS_HPP