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/compactHashtable.hpp"
30 #include "compiler/compiler_globals.hpp"
31 #include "compiler/compilerDefinitions.hpp"
32 #include "memory/allocation.hpp"
33 #include "memory/metaspaceClosure.hpp"
34 #include "oops/instanceKlass.hpp"
35 #include "oops/method.hpp"
36 #include "oops/objArrayKlass.hpp"
37 #include "runtime/handles.hpp"
38 #include "runtime/mutexLocker.hpp"
39 #include "utilities/resizableHashTable.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.
292
293 static bool is_klass_loaded(Klass* k) {
294 if (have_data()) {
295 // If we're running in AOT mode some classes may not be loaded yet
296 if (k->is_objArray_klass()) {
297 k = ObjArrayKlass::cast(k)->bottom_klass();
298 }
299 if (k->is_instance_klass()) {
300 return InstanceKlass::cast(k)->is_loaded();
301 }
302 }
303 return true;
304 }
305
306 template<typename Function>
307 static void iterate(const Function& fn) { iterate(const_cast<Function&>(fn)); }
308
309 template<typename Function>
310 static void iterate(Function& fn) { // lambda enabled API
311 TrainingDataLocker l;
312 if (have_data()) {
313 archived_training_data_dictionary()->iterate(fn);
314 }
315 if (need_data()) {
316 training_data_set()->iterate(fn);
317 }
318 }
319
320 virtual MethodTrainingData* as_MethodTrainingData() const { return nullptr; }
321 virtual KlassTrainingData* as_KlassTrainingData() const { return nullptr; }
322 virtual CompileTrainingData* as_CompileTrainingData() const { return nullptr; }
323 bool is_MethodTrainingData() const { return as_MethodTrainingData() != nullptr; }
324 bool is_KlassTrainingData() const { return as_KlassTrainingData() != nullptr; }
325 bool is_CompileTrainingData() const { return as_CompileTrainingData() != nullptr; }
326
327 virtual void prepare(Visitor& visitor) = 0;
328 virtual void cleanup(Visitor& visitor) = 0;
329
330 static void initialize() NOT_CDS_RETURN;
331
332 static void verify();
333
334 // Widget for recording dependencies, as an N-to-M graph relation,
335 // possibly cyclic.
336 template<typename E>
337 class DepList : public StackObj {
338 GrowableArrayCHeap<E, mtCompiler>* _deps_dyn;
339 Array<E>* _deps;
340 public:
341 DepList() {
342 _deps_dyn = nullptr;
343 _deps = nullptr;
344 }
345
346 int length() const {
347 TrainingDataLocker::assert_locked_or_snapshotted();
348 return (_deps_dyn != nullptr ? _deps_dyn->length()
349 : _deps != nullptr ? _deps->length()
350 : 0);
351 }
352 E* adr_at(int i) const {
353 TrainingDataLocker::assert_locked_or_snapshotted();
354 return (_deps_dyn != nullptr ? _deps_dyn->adr_at(i)
355 : _deps != nullptr ? _deps->adr_at(i)
356 : nullptr);
357 }
358 E at(int i) const {
359 TrainingDataLocker::assert_locked_or_snapshotted();
360 assert(i >= 0 && i < length(), "oob");
361 return *adr_at(i);
362 }
363 bool append_if_missing(E dep) {
364 TrainingDataLocker::assert_can_add();
365 if (_deps_dyn == nullptr) {
366 _deps_dyn = new GrowableArrayCHeap<E, mtCompiler>(10);
367 _deps_dyn->append(dep);
368 return true;
369 } else {
370 return _deps_dyn->append_if_missing(dep);
371 }
372 }
373 bool remove_if_existing(E dep) {
374 TrainingDataLocker::assert_can_add();
375 if (_deps_dyn != nullptr) {
376 return _deps_dyn->remove_if_existing(dep);
377 }
378 return false;
379 }
380 void clear() {
381 TrainingDataLocker::assert_can_add();
382 if (_deps_dyn != nullptr) {
383 _deps_dyn->clear();
384 }
385 }
386 void append(E dep) {
387 TrainingDataLocker::assert_can_add();
388 if (_deps_dyn == nullptr) {
389 _deps_dyn = new GrowableArrayCHeap<E, mtCompiler>(10);
390 }
391 _deps_dyn->append(dep);
392 }
393 bool contains(E dep) {
394 TrainingDataLocker::assert_locked();
395 for (int i = 0; i < length(); i++) {
396 if (dep == at(i)) {
397 return true; // found
398 }
399 }
400 return false; // not found
401 }
402
403 #if INCLUDE_CDS
404 void remove_unshareable_info() {
405 _deps_dyn = nullptr;
406 }
407 #endif
408 void prepare();
409 void metaspace_pointers_do(MetaspaceClosure *iter);
751 int _invocation_count;
752 int _backedge_count;
753
754 MethodTrainingData();
755 MethodTrainingData(Method* method, KlassTrainingData* ktd) : TrainingData(method) {
756 _klass = ktd;
757 _holder = method;
758 for (int i = 0; i < CompLevel_count - 1; i++) {
759 _last_toplevel_compiles[i] = nullptr;
760 }
761 _highest_top_level = CompLevel_none;
762 _level_mask = 0;
763 _was_toplevel = false;
764 _invocation_count = 0;
765 _backedge_count = 0;
766 }
767
768 static int level_mask(int level) {
769 return ((level & 0xF) != level ? 0 : 1 << level);
770 }
771
772 public:
773 KlassTrainingData* klass() const { return _klass; }
774 bool has_holder() const { return _holder != nullptr; }
775 Method* holder() const { return _holder; }
776 bool only_inlined() const { return !_was_toplevel; }
777 bool saw_level(CompLevel l) const { return (_level_mask & level_mask(l)) != 0; }
778 int highest_top_level() const { return _highest_top_level; }
779 MethodData* final_profile() const { return _final_profile; }
780 int invocation_count() const { return _invocation_count; }
781 int backedge_count() const { return _backedge_count; }
782
783 Symbol* name() const {
784 precond(has_holder());
785 return holder()->name();
786 }
787 Symbol* signature() const {
788 precond(has_holder());
789 return holder()->signature();
790 }
791
792 CompileTrainingData* last_toplevel_compile(int level) const {
793 if (level > CompLevel_none) {
794 return _last_toplevel_compiles[level - 1];
795 }
796 return nullptr;
797 }
|
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/compactHashtable.hpp"
30 #include "compiler/compiler_globals.hpp"
31 #include "compiler/compilerDefinitions.hpp"
32 #include "memory/allocation.hpp"
33 #include "memory/metaspaceClosure.hpp"
34 #include "oops/instanceKlass.hpp"
35 #include "oops/method.hpp"
36 #include "oops/objArrayKlass.hpp"
37 #include "runtime/handles.hpp"
38 #include "runtime/mutexLocker.hpp"
39 #include "utilities/count_leading_zeros.hpp"
40 #include "utilities/resizableHashTable.hpp"
41
42 class ciEnv;
43 class ciBaseObject;
44 class CompileTask;
45 class CompileTrainingData;
46 class KlassTrainingData;
47 class MethodTrainingData;
48
49 // Base class for all the training data varieties
50 class TrainingData : public Metadata {
51 friend KlassTrainingData;
52 friend MethodTrainingData;
53 friend CompileTrainingData;
54 public:
55 // Key is used to insert any TrainingData (TD) object into a hash tables. The key is currently a
56 // pointer to a metaspace object the TD is associated with. For example,
57 // for KlassTrainingData it's an InstanceKlass, for MethodTrainingData it's a Method.
58 // The utility of the these hash tables is to be able to find a TD object for a given metaspace
59 // metaspace object.
293
294 static bool is_klass_loaded(Klass* k) {
295 if (have_data()) {
296 // If we're running in AOT mode some classes may not be loaded yet
297 if (k->is_objArray_klass()) {
298 k = ObjArrayKlass::cast(k)->bottom_klass();
299 }
300 if (k->is_instance_klass()) {
301 return InstanceKlass::cast(k)->is_loaded();
302 }
303 }
304 return true;
305 }
306
307 template<typename Function>
308 static void iterate(const Function& fn) { iterate(const_cast<Function&>(fn)); }
309
310 template<typename Function>
311 static void iterate(Function& fn) { // lambda enabled API
312 TrainingDataLocker l;
313 if (have_data() && !need_data()) {
314 archived_training_data_dictionary()->iterate_all([&](TrainingData* td) { fn(td); });
315 }
316 if (need_data()) {
317 training_data_set()->iterate(fn);
318 }
319 }
320
321 virtual MethodTrainingData* as_MethodTrainingData() const { return nullptr; }
322 virtual KlassTrainingData* as_KlassTrainingData() const { return nullptr; }
323 virtual CompileTrainingData* as_CompileTrainingData() const { return nullptr; }
324 bool is_MethodTrainingData() const { return as_MethodTrainingData() != nullptr; }
325 bool is_KlassTrainingData() const { return as_KlassTrainingData() != nullptr; }
326 bool is_CompileTrainingData() const { return as_CompileTrainingData() != nullptr; }
327
328 virtual void prepare(Visitor& visitor) = 0;
329 virtual void cleanup(Visitor& visitor) = 0;
330
331 static void initialize() NOT_CDS_RETURN;
332
333 static void verify() NOT_CDS_RETURN;
334
335 // Widget for recording dependencies, as an N-to-M graph relation,
336 // possibly cyclic.
337 template<typename E>
338 class DepList : public StackObj {
339 static const int INITIAL_CAPACITY = 10;
340
341 GrowableArrayCHeap<E, mtCompiler>* _deps_dyn;
342 Array<E>* _deps;
343
344 void copy_on_write_if_necessary() {
345 TrainingDataLocker::assert_locked_or_snapshotted();
346 if (_deps != nullptr && _deps_dyn == nullptr) {
347 _deps_dyn = new GrowableArrayCHeap<E, mtCompiler>(length() + INITIAL_CAPACITY);
348 for (int i = 0; _deps->length(); i++) {
349 _deps_dyn->append(_deps->at(i));
350 }
351 _deps = nullptr;
352 }
353 }
354 public:
355 DepList() {
356 _deps_dyn = nullptr;
357 _deps = nullptr;
358 }
359
360 int length() const {
361 TrainingDataLocker::assert_locked_or_snapshotted();
362 return (_deps_dyn != nullptr ? _deps_dyn->length()
363 : _deps != nullptr ? _deps->length()
364 : 0);
365 }
366 E at(int i) const {
367 TrainingDataLocker::assert_locked_or_snapshotted();
368 assert(i >= 0 && i < length(), "oob");
369 if (_deps_dyn != nullptr) {
370 return _deps_dyn->at(i);
371 } else if (_deps != nullptr) {
372 return _deps->at(i);
373 } else ShouldNotReachHere();
374 }
375 bool append_if_missing(E dep) {
376 TrainingDataLocker::assert_can_add();
377 copy_on_write_if_necessary();
378 if (_deps_dyn == nullptr) {
379 _deps_dyn = new GrowableArrayCHeap<E, mtCompiler>(INITIAL_CAPACITY);
380 _deps_dyn->append(dep);
381 return true;
382 } else {
383 return _deps_dyn->append_if_missing(dep);
384 }
385 }
386 bool remove_if_existing(E dep) {
387 TrainingDataLocker::assert_can_add();
388 copy_on_write_if_necessary();
389 if (_deps_dyn != nullptr) {
390 return _deps_dyn->remove_if_existing(dep);
391 }
392 return false;
393 }
394 void clear() {
395 TrainingDataLocker::assert_can_add();
396 if (_deps_dyn != nullptr) {
397 _deps_dyn->clear();
398 }
399 _deps = nullptr;
400 }
401 void append(E dep) {
402 TrainingDataLocker::assert_can_add();
403 copy_on_write_if_necessary();
404 if (_deps_dyn == nullptr) {
405 _deps_dyn = new GrowableArrayCHeap<E, mtCompiler>(INITIAL_CAPACITY);
406 }
407 _deps_dyn->append(dep);
408 }
409 bool contains(E dep) {
410 TrainingDataLocker::assert_locked();
411 for (int i = 0; i < length(); i++) {
412 if (dep == at(i)) {
413 return true; // found
414 }
415 }
416 return false; // not found
417 }
418
419 #if INCLUDE_CDS
420 void remove_unshareable_info() {
421 _deps_dyn = nullptr;
422 }
423 #endif
424 void prepare();
425 void metaspace_pointers_do(MetaspaceClosure *iter);
767 int _invocation_count;
768 int _backedge_count;
769
770 MethodTrainingData();
771 MethodTrainingData(Method* method, KlassTrainingData* ktd) : TrainingData(method) {
772 _klass = ktd;
773 _holder = method;
774 for (int i = 0; i < CompLevel_count - 1; i++) {
775 _last_toplevel_compiles[i] = nullptr;
776 }
777 _highest_top_level = CompLevel_none;
778 _level_mask = 0;
779 _was_toplevel = false;
780 _invocation_count = 0;
781 _backedge_count = 0;
782 }
783
784 static int level_mask(int level) {
785 return ((level & 0xF) != level ? 0 : 1 << level);
786 }
787 static CompLevel highest_level(int mask) {
788 if (mask == 0) return (CompLevel) 0;
789 int diff = (count_leading_zeros(level_mask(0)) - count_leading_zeros(mask));
790 return (CompLevel) diff;
791 }
792
793 public:
794 KlassTrainingData* klass() const { return _klass; }
795 bool has_holder() const { return _holder != nullptr; }
796 Method* holder() const { return _holder; }
797 bool only_inlined() const { return !_was_toplevel; }
798 bool saw_level(CompLevel l) const { return (_level_mask & level_mask(l)) != 0; }
799 int highest_level() const { return highest_level(_level_mask); }
800 int highest_top_level() const { return _highest_top_level; }
801 MethodData* final_profile() const { return _final_profile; }
802 int invocation_count() const { return _invocation_count; }
803 int backedge_count() const { return _backedge_count; }
804
805 Symbol* name() const {
806 precond(has_holder());
807 return holder()->name();
808 }
809 Symbol* signature() const {
810 precond(has_holder());
811 return holder()->signature();
812 }
813
814 CompileTrainingData* last_toplevel_compile(int level) const {
815 if (level > CompLevel_none) {
816 return _last_toplevel_compiles[level - 1];
817 }
818 return nullptr;
819 }
|