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) {
|