< prev index next >

src/hotspot/share/oops/trainingData.hpp

Print this page

 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_OOPS_TRAININGDATA_HPP
 26 #define SHARE_OOPS_TRAININGDATA_HPP
 27 
 28 #include "cds/cdsConfig.hpp"
 29 #include "classfile/classLoaderData.hpp"
 30 #include "classfile/compactHashtable.hpp"
 31 #include "compiler/compilerDefinitions.hpp"
 32 #include "compiler/compiler_globals.hpp"
 33 #include "memory/allocation.hpp"
 34 #include "memory/metaspaceClosure.hpp"
 35 #include "oops/instanceKlass.hpp"
 36 #include "oops/method.hpp"

 37 #include "runtime/handles.hpp"
 38 #include "runtime/mutexLocker.hpp"

 39 #include "utilities/resizeableResourceHash.hpp"
 40 
 41 class ciEnv;
 42 class ciBaseObject;
 43 class CompileTask;
 44 class CompileTrainingData;
 45 class KlassTrainingData;
 46 class MethodTrainingData;
 47 
 48 // Base class for all the training data varieties
 49 class TrainingData : public Metadata {
 50   friend KlassTrainingData;
 51   friend MethodTrainingData;
 52   friend CompileTrainingData;
 53 public:
 54   // Key is used to insert any TrainingData (TD) object into a hash tables. The key is currently a
 55   // pointer to a metaspace object the TD is associated with. For example,
 56   // for KlassTrainingData it's an InstanceKlass, for MethodTrainingData it's a Method.
 57   // The utility of the these hash tables is to be able to find a TD object for a given metaspace
 58   // metaspace object.

266     TrainingData* training_data() {
267       return _training_data;
268     }
269   };
270   typedef GrowableArrayCHeap<DumpTimeTrainingDataInfo, mtClassShared> DumptimeTrainingDataDictionary;
271   // A temporary container that is used to accumulate and filter TD during dumping
272   static DumptimeTrainingDataDictionary* _dumptime_training_data_dictionary;
273 
274   static TrainingDataSet* training_data_set() { return &_training_data_set; }
275   static TrainingDataDictionary* archived_training_data_dictionary() { return &_archived_training_data_dictionary; }
276 
277  public:
278   // Returns the key under which this TD is installed, or else
279   // Key::EMPTY if it is not installed.
280   const Key* key() const { return &_key; }
281 
282   static bool have_data() { return AOTReplayTraining;  } // Going to read
283   static bool need_data() { return AOTRecordTraining;  } // Going to write
284   static bool assembling_data() { return have_data() && CDSConfig::is_dumping_final_static_archive() && CDSConfig::is_dumping_aot_linked_classes(); }
285 













286   template<typename Function>
287   static void iterate(const Function& fn) { iterate(const_cast<Function&>(fn)); }
288 
289   template<typename Function>
290   static void iterate(Function& fn) { // lambda enabled API
291     TrainingDataLocker l;
292     if (have_data()) {
293       archived_training_data_dictionary()->iterate(fn);
294     }
295     if (need_data()) {
296       training_data_set()->iterate(fn);
297     }
298   }
299 
300   virtual MethodTrainingData*   as_MethodTrainingData()  const { return nullptr; }
301   virtual KlassTrainingData*    as_KlassTrainingData()   const { return nullptr; }
302   virtual CompileTrainingData*  as_CompileTrainingData() const { return nullptr; }
303   bool is_MethodTrainingData()  const { return as_MethodTrainingData()  != nullptr; }
304   bool is_KlassTrainingData()   const { return as_KlassTrainingData()   != nullptr; }
305   bool is_CompileTrainingData() const { return as_CompileTrainingData() != nullptr; }
306 
307   virtual void prepare(Visitor& visitor) = 0;
308   virtual void cleanup(Visitor& visitor) = 0;
309 
310   static void initialize() NOT_CDS_RETURN;
311 
312   static void verify();
313 
314   // Widget for recording dependencies, as an N-to-M graph relation,
315   // possibly cyclic.
316   template<typename E>
317   class DepList : public StackObj {
318     GrowableArrayCHeap<E, mtCompiler>* _deps_dyn;
319     Array<E>*                          _deps;
320   public:
321     DepList() {
322       _deps_dyn = nullptr;
323       _deps = nullptr;
324     }
325 
326     int length() const {
327       return (_deps_dyn != nullptr ? _deps_dyn->length()
328               : _deps   != nullptr ? _deps->length()
329               : 0);
330     }
331     E* adr_at(int i) const {
332       return (_deps_dyn != nullptr ? _deps_dyn->adr_at(i)

400     assert(need_data() || have_data(), "");
401     if (TrainingDataLocker::can_add()) {
402       return new (mtClassShared) TrainingDataType(args...);
403     }
404     return nullptr;
405   }
406 };
407 
408 // Training data that is associated with an InstanceKlass
409 class KlassTrainingData : public TrainingData {
410   friend TrainingData;
411   friend CompileTrainingData;
412 
413   // Used by CDS. These classes need to access the private default constructor.
414   template <class T> friend class CppVtableTesterA;
415   template <class T> friend class CppVtableTesterB;
416   template <class T> friend class CppVtableCloner;
417 
418   // cross-link to live klass, or null if not loaded or encountered yet
419   InstanceKlass* _holder;
420   jobject _holder_mirror;   // extra link to prevent unloading by GC
421 
422   DepList<CompileTrainingData*> _comp_deps; // compiles that depend on me
423 
424   KlassTrainingData();
425   KlassTrainingData(InstanceKlass* klass);
426 
427   int comp_dep_count() const {
428     TrainingDataLocker::assert_locked();
429     return _comp_deps.length();
430   }
431   CompileTrainingData* comp_dep(int i) const {
432     TrainingDataLocker::assert_locked();
433     return _comp_deps.at(i);
434   }
435   void add_comp_dep(CompileTrainingData* ctd) {
436     TrainingDataLocker::assert_locked();
437      _comp_deps.append_if_missing(ctd);
438   }
439   void remove_comp_dep(CompileTrainingData* ctd) {
440     TrainingDataLocker::assert_locked();
441      _comp_deps.remove_if_existing(ctd);
442   }
443 
444  public:
445   Symbol* name() const {
446     precond(has_holder());
447     return holder()->name();
448   }
449   bool has_holder()       const { return _holder != nullptr; }
450   InstanceKlass* holder() const { return _holder; }
451 
452   static KlassTrainingData* make(InstanceKlass* holder,
453                                  bool null_if_not_found = false) NOT_CDS_RETURN_(nullptr);
454   static KlassTrainingData* find(InstanceKlass* holder) {
455     return make(holder, true);
456   }
457   virtual KlassTrainingData* as_KlassTrainingData() const { return const_cast<KlassTrainingData*>(this); };
458 
459   ClassLoaderData* class_loader_data() {
460     assert(has_holder(), "");
461     return holder()->class_loader_data();
462   }
463   void notice_fully_initialized() NOT_CDS_RETURN;

720   bool _was_toplevel;
721   // metadata snapshots of final state:
722   MethodCounters* _final_counters;
723   MethodData*     _final_profile;
724 
725   MethodTrainingData();
726   MethodTrainingData(Method* method, KlassTrainingData* ktd) : TrainingData(method) {
727     _klass = ktd;
728     _holder = method;
729     for (int i = 0; i < CompLevel_count - 1; i++) {
730       _last_toplevel_compiles[i] = nullptr;
731     }
732     _highest_top_level = CompLevel_none;
733     _level_mask = 0;
734     _was_toplevel = false;
735   }
736 
737   static int level_mask(int level) {
738     return ((level & 0xF) != level ? 0 : 1 << level);
739   }





740 
741  public:
742   KlassTrainingData* klass()  const { return _klass; }
743   bool has_holder()           const { return _holder != nullptr; }
744   Method* holder()            const { return _holder; }
745   bool only_inlined()         const { return !_was_toplevel; }
746   bool saw_level(CompLevel l) const { return (_level_mask & level_mask(l)) != 0; }

747   int highest_top_level()     const { return _highest_top_level; }
748   MethodData* final_profile() const { return _final_profile; }
749 
750   Symbol* name() const {
751     precond(has_holder());
752     return holder()->name();
753   }
754   Symbol* signature() const {
755     precond(has_holder());
756     return holder()->signature();
757   }
758 
759   CompileTrainingData* last_toplevel_compile(int level) const {
760     if (level > CompLevel_none) {
761       return _last_toplevel_compiles[level - 1];
762     }
763     return nullptr;
764   }
765 
766   void notice_compilation(int level, bool inlined = false) {

 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_OOPS_TRAININGDATA_HPP
 26 #define SHARE_OOPS_TRAININGDATA_HPP
 27 
 28 #include "cds/cdsConfig.hpp"
 29 #include "classfile/classLoaderData.hpp"
 30 #include "classfile/compactHashtable.hpp"
 31 #include "compiler/compilerDefinitions.hpp"
 32 #include "compiler/compiler_globals.hpp"
 33 #include "memory/allocation.hpp"
 34 #include "memory/metaspaceClosure.hpp"
 35 #include "oops/instanceKlass.hpp"
 36 #include "oops/method.hpp"
 37 #include "oops/objArrayKlass.hpp"
 38 #include "runtime/handles.hpp"
 39 #include "runtime/mutexLocker.hpp"
 40 #include "utilities/count_leading_zeros.hpp"
 41 #include "utilities/resizeableResourceHash.hpp"
 42 
 43 class ciEnv;
 44 class ciBaseObject;
 45 class CompileTask;
 46 class CompileTrainingData;
 47 class KlassTrainingData;
 48 class MethodTrainingData;
 49 
 50 // Base class for all the training data varieties
 51 class TrainingData : public Metadata {
 52   friend KlassTrainingData;
 53   friend MethodTrainingData;
 54   friend CompileTrainingData;
 55 public:
 56   // Key is used to insert any TrainingData (TD) object into a hash tables. The key is currently a
 57   // pointer to a metaspace object the TD is associated with. For example,
 58   // for KlassTrainingData it's an InstanceKlass, for MethodTrainingData it's a Method.
 59   // The utility of the these hash tables is to be able to find a TD object for a given metaspace
 60   // metaspace object.

268     TrainingData* training_data() {
269       return _training_data;
270     }
271   };
272   typedef GrowableArrayCHeap<DumpTimeTrainingDataInfo, mtClassShared> DumptimeTrainingDataDictionary;
273   // A temporary container that is used to accumulate and filter TD during dumping
274   static DumptimeTrainingDataDictionary* _dumptime_training_data_dictionary;
275 
276   static TrainingDataSet* training_data_set() { return &_training_data_set; }
277   static TrainingDataDictionary* archived_training_data_dictionary() { return &_archived_training_data_dictionary; }
278 
279  public:
280   // Returns the key under which this TD is installed, or else
281   // Key::EMPTY if it is not installed.
282   const Key* key() const { return &_key; }
283 
284   static bool have_data() { return AOTReplayTraining;  } // Going to read
285   static bool need_data() { return AOTRecordTraining;  } // Going to write
286   static bool assembling_data() { return have_data() && CDSConfig::is_dumping_final_static_archive() && CDSConfig::is_dumping_aot_linked_classes(); }
287 
288   static bool is_klass_loaded(Klass* k) {
289     if (have_data()) {
290       // If we're running in AOT mode some classes may not be loaded yet
291       if (k->is_objArray_klass()) {
292         k = ObjArrayKlass::cast(k)->bottom_klass();
293       }
294       if (k->is_instance_klass()) {
295         return InstanceKlass::cast(k)->is_loaded();
296       }
297     }
298     return true;
299   }
300 
301   template<typename Function>
302   static void iterate(const Function& fn) { iterate(const_cast<Function&>(fn)); }
303 
304   template<typename Function>
305   static void iterate(Function& fn) { // lambda enabled API
306     TrainingDataLocker l;
307     if (have_data()) {
308       archived_training_data_dictionary()->iterate(fn);
309     }
310     if (need_data()) {
311       training_data_set()->iterate(fn);
312     }
313   }
314 
315   virtual MethodTrainingData*   as_MethodTrainingData()  const { return nullptr; }
316   virtual KlassTrainingData*    as_KlassTrainingData()   const { return nullptr; }
317   virtual CompileTrainingData*  as_CompileTrainingData() const { return nullptr; }
318   bool is_MethodTrainingData()  const { return as_MethodTrainingData()  != nullptr; }
319   bool is_KlassTrainingData()   const { return as_KlassTrainingData()   != nullptr; }
320   bool is_CompileTrainingData() const { return as_CompileTrainingData() != nullptr; }
321 
322   virtual void prepare(Visitor& visitor) = 0;
323   virtual void cleanup(Visitor& visitor) = 0;
324 
325   static void initialize() NOT_CDS_RETURN;
326 
327   static void verify() NOT_CDS_RETURN;
328 
329   // Widget for recording dependencies, as an N-to-M graph relation,
330   // possibly cyclic.
331   template<typename E>
332   class DepList : public StackObj {
333     GrowableArrayCHeap<E, mtCompiler>* _deps_dyn;
334     Array<E>*                          _deps;
335   public:
336     DepList() {
337       _deps_dyn = nullptr;
338       _deps = nullptr;
339     }
340 
341     int length() const {
342       return (_deps_dyn != nullptr ? _deps_dyn->length()
343               : _deps   != nullptr ? _deps->length()
344               : 0);
345     }
346     E* adr_at(int i) const {
347       return (_deps_dyn != nullptr ? _deps_dyn->adr_at(i)

415     assert(need_data() || have_data(), "");
416     if (TrainingDataLocker::can_add()) {
417       return new (mtClassShared) TrainingDataType(args...);
418     }
419     return nullptr;
420   }
421 };
422 
423 // Training data that is associated with an InstanceKlass
424 class KlassTrainingData : public TrainingData {
425   friend TrainingData;
426   friend CompileTrainingData;
427 
428   // Used by CDS. These classes need to access the private default constructor.
429   template <class T> friend class CppVtableTesterA;
430   template <class T> friend class CppVtableTesterB;
431   template <class T> friend class CppVtableCloner;
432 
433   // cross-link to live klass, or null if not loaded or encountered yet
434   InstanceKlass* _holder;

435 
436   DepList<CompileTrainingData*> _comp_deps; // compiles that depend on me
437 
438   KlassTrainingData();
439   KlassTrainingData(InstanceKlass* klass);
440 
441   int comp_dep_count() const {
442     TrainingDataLocker::assert_locked();
443     return _comp_deps.length();
444   }
445   CompileTrainingData* comp_dep(int i) const {
446     TrainingDataLocker::assert_locked();
447     return _comp_deps.at(i);
448   }
449   void add_comp_dep(CompileTrainingData* ctd) {
450     TrainingDataLocker::assert_locked();
451      _comp_deps.append_if_missing(ctd);
452   }
453   void remove_comp_dep(CompileTrainingData* ctd) {
454     TrainingDataLocker::assert_locked();
455      _comp_deps.remove_if_existing(ctd);
456   }

457  public:
458   Symbol* name() const {
459     precond(has_holder());
460     return holder()->name();
461   }
462   bool has_holder()       const { return _holder != nullptr; }
463   InstanceKlass* holder() const { return _holder; }
464 
465   static KlassTrainingData* make(InstanceKlass* holder,
466                                  bool null_if_not_found = false) NOT_CDS_RETURN_(nullptr);
467   static KlassTrainingData* find(InstanceKlass* holder) {
468     return make(holder, true);
469   }
470   virtual KlassTrainingData* as_KlassTrainingData() const { return const_cast<KlassTrainingData*>(this); };
471 
472   ClassLoaderData* class_loader_data() {
473     assert(has_holder(), "");
474     return holder()->class_loader_data();
475   }
476   void notice_fully_initialized() NOT_CDS_RETURN;

733   bool _was_toplevel;
734   // metadata snapshots of final state:
735   MethodCounters* _final_counters;
736   MethodData*     _final_profile;
737 
738   MethodTrainingData();
739   MethodTrainingData(Method* method, KlassTrainingData* ktd) : TrainingData(method) {
740     _klass = ktd;
741     _holder = method;
742     for (int i = 0; i < CompLevel_count - 1; i++) {
743       _last_toplevel_compiles[i] = nullptr;
744     }
745     _highest_top_level = CompLevel_none;
746     _level_mask = 0;
747     _was_toplevel = false;
748   }
749 
750   static int level_mask(int level) {
751     return ((level & 0xF) != level ? 0 : 1 << level);
752   }
753   static CompLevel highest_level(int mask) {
754     if (mask == 0)  return (CompLevel) 0;
755     int diff = (count_leading_zeros(level_mask(0)) - count_leading_zeros(mask));
756     return (CompLevel) diff;
757   }
758 
759  public:
760   KlassTrainingData* klass()  const { return _klass; }
761   bool has_holder()           const { return _holder != nullptr; }
762   Method* holder()            const { return _holder; }
763   bool only_inlined()         const { return !_was_toplevel; }
764   bool saw_level(CompLevel l) const { return (_level_mask & level_mask(l)) != 0; }
765   int highest_level()         const { return highest_level(_level_mask); }
766   int highest_top_level()     const { return _highest_top_level; }
767   MethodData* final_profile() const { return _final_profile; }
768 
769   Symbol* name() const {
770     precond(has_holder());
771     return holder()->name();
772   }
773   Symbol* signature() const {
774     precond(has_holder());
775     return holder()->signature();
776   }
777 
778   CompileTrainingData* last_toplevel_compile(int level) const {
779     if (level > CompLevel_none) {
780       return _last_toplevel_compiles[level - 1];
781     }
782     return nullptr;
783   }
784 
785   void notice_compilation(int level, bool inlined = false) {
< prev index next >