1 /*
  2  * Copyright (c) 2021, 2023, 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_CDS_DUMPTIMECLASSINFO_HPP
 26 #define SHARE_CDS_DUMPTIMECLASSINFO_HPP
 27 
 28 #include "cds/archiveBuilder.hpp"
 29 #include "cds/archiveUtils.hpp"
 30 #include "cds/cdsConfig.hpp"
 31 #include "cds/metaspaceShared.hpp"
 32 #include "classfile/compactHashtable.hpp"
 33 #include "memory/metaspaceClosure.hpp"
 34 #include "oops/instanceKlass.hpp"
 35 #include "prims/jvmtiExport.hpp"
 36 #include "utilities/growableArray.hpp"
 37 
 38 class Method;
 39 class Symbol;
 40 
 41 class DumpTimeClassInfo: public CHeapObj<mtClass> {
 42   bool                         _excluded;
 43   bool                         _is_early_klass;
 44   bool                         _has_checked_exclusion;
 45   bool                         _can_be_preinited;
 46   bool                         _has_done_preinit_check;
 47   bool                         _forced_preinit;
 48 
 49   class DTLoaderConstraint {
 50     Symbol* _name;
 51     char _loader_type1;
 52     char _loader_type2;
 53   public:
 54     DTLoaderConstraint() : _name(nullptr), _loader_type1('0'), _loader_type2('0') {}
 55     DTLoaderConstraint(Symbol* name, char l1, char l2) : _name(name), _loader_type1(l1), _loader_type2(l2) {
 56       Symbol::maybe_increment_refcount(_name);
 57     }
 58     DTLoaderConstraint(const DTLoaderConstraint& src) {
 59       _name = src._name;
 60       _loader_type1 = src._loader_type1;
 61       _loader_type2 = src._loader_type2;
 62       Symbol::maybe_increment_refcount(_name);
 63     }
 64     DTLoaderConstraint& operator=(DTLoaderConstraint src) {
 65       swap(_name, src._name); // c++ copy-and-swap idiom
 66       _loader_type1 = src._loader_type1;
 67       _loader_type2 = src._loader_type2;
 68       return *this;
 69     }
 70     ~DTLoaderConstraint() {
 71       Symbol::maybe_decrement_refcount(_name);
 72     }
 73 
 74     bool equals(const DTLoaderConstraint& t) {
 75       return t._name == _name &&
 76              ((t._loader_type1 == _loader_type1 && t._loader_type2 == _loader_type2) ||
 77               (t._loader_type2 == _loader_type1 && t._loader_type1 == _loader_type2));
 78     }
 79     void metaspace_pointers_do(MetaspaceClosure* it) {
 80       it->push(&_name);
 81     }
 82 
 83     Symbol* name()      { return _name;         }
 84     char loader_type1() { return _loader_type1; }
 85     char loader_type2() { return _loader_type2; }
 86   };
 87 
 88   class DTVerifierConstraint {
 89     Symbol* _name;
 90     Symbol* _from_name;
 91   public:
 92     DTVerifierConstraint() : _name(nullptr), _from_name(nullptr) {}
 93     DTVerifierConstraint(Symbol* n, Symbol* fn) : _name(n), _from_name(fn) {
 94       Symbol::maybe_increment_refcount(_name);
 95       Symbol::maybe_increment_refcount(_from_name);
 96     }
 97     DTVerifierConstraint(const DTVerifierConstraint& src) {
 98       _name = src._name;
 99       _from_name = src._from_name;
100       Symbol::maybe_increment_refcount(_name);
101       Symbol::maybe_increment_refcount(_from_name);
102     }
103     DTVerifierConstraint& operator=(DTVerifierConstraint src) {
104       swap(_name, src._name); // c++ copy-and-swap idiom
105       swap(_from_name, src._from_name); // c++ copy-and-swap idiom
106       return *this;
107     }
108     ~DTVerifierConstraint() {
109       Symbol::maybe_decrement_refcount(_name);
110       Symbol::maybe_decrement_refcount(_from_name);
111     }
112     bool equals(Symbol* n, Symbol* fn) {
113       return (_name == n) && (_from_name == fn);
114     }
115     void metaspace_pointers_do(MetaspaceClosure* it) {
116       it->push(&_name);
117       it->push(&_from_name);
118     }
119 
120     Symbol* name()      { return _name;      }
121     Symbol* from_name() { return _from_name; }
122   };
123 
124 public:
125   InstanceKlass*               _klass;
126   InstanceKlass*               _nest_host;
127   bool                         _failed_verification;
128   bool                         _is_archived_lambda_proxy;
129   int                          _id;
130   int                          _clsfile_size;
131   int                          _clsfile_crc32;
132   GrowableArray<DTVerifierConstraint>* _verifier_constraints;
133   GrowableArray<char>*                 _verifier_constraint_flags;
134   GrowableArray<DTLoaderConstraint>*   _loader_constraints;
135   GrowableArray<int>*                  _enum_klass_static_fields;
136 
137   DumpTimeClassInfo() {
138     _klass = nullptr;
139     _nest_host = nullptr;
140     _failed_verification = false;
141     _is_archived_lambda_proxy = false;
142     _has_checked_exclusion = false;
143     _can_be_preinited = false;
144     _has_done_preinit_check = false;
145     _forced_preinit = false;
146     _id = -1;
147     _clsfile_size = -1;
148     _clsfile_crc32 = -1;
149     _excluded = false;
150     _is_early_klass = JvmtiExport::is_early_phase();
151     _verifier_constraints = nullptr;
152     _verifier_constraint_flags = nullptr;
153     _loader_constraints = nullptr;
154     _enum_klass_static_fields = nullptr;
155   }
156   DumpTimeClassInfo& operator=(const DumpTimeClassInfo&) = delete;
157   ~DumpTimeClassInfo();
158 
159   void add_verification_constraint(InstanceKlass* k, Symbol* name,
160          Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object);
161   void record_linking_constraint(Symbol* name, Handle loader1, Handle loader2);
162   void add_enum_klass_static_field(int archived_heap_root_index);
163   int  enum_klass_static_field(int which_field);
164   bool is_builtin();
165 
166 private:
167   template <typename T>
168   static int array_length_or_zero(GrowableArray<T>* array) {
169     if (array == nullptr) {
170       return 0;
171     } else {
172       return array->length();
173     }
174   }
175 
176 public:
177 
178   int num_verifier_constraints() const {
179     return array_length_or_zero(_verifier_constraint_flags);
180   }
181 
182   int num_loader_constraints() const {
183     return array_length_or_zero(_loader_constraints);
184   }
185 
186   int num_enum_klass_static_fields() const {
187     return array_length_or_zero(_enum_klass_static_fields);
188   }
189 
190   void metaspace_pointers_do(MetaspaceClosure* it) {
191     it->push(&_klass);
192     it->push(&_nest_host);
193     if (_verifier_constraints != nullptr) {
194       for (int i = 0; i < _verifier_constraints->length(); i++) {
195         _verifier_constraints->adr_at(i)->metaspace_pointers_do(it);
196       }
197     }
198     if (_loader_constraints != nullptr) {
199       for (int i = 0; i < _loader_constraints->length(); i++) {
200         _loader_constraints->adr_at(i)->metaspace_pointers_do(it);
201       }
202     }
203   }
204 
205   bool is_excluded();
206 
207   // Was this class loaded while JvmtiExport::is_early_phase()==true
208   bool is_early_klass() {
209     return _is_early_klass;
210   }
211 
212   // simple accessors
213   void set_excluded()                               { _excluded = true; }
214   bool has_checked_exclusion() const                { return _has_checked_exclusion; }
215   void set_has_checked_exclusion()                  { _has_checked_exclusion = true; }
216   bool failed_verification() const                  { return _failed_verification; }
217   void set_failed_verification()                    { _failed_verification = true; }
218   InstanceKlass* nest_host() const                  { return _nest_host; }
219   void set_nest_host(InstanceKlass* nest_host)      { _nest_host = nest_host; }
220 
221   void force_preinit()                              { _forced_preinit = true; }
222   bool is_forced_preinit() const                    { return _forced_preinit; }
223   bool can_be_preinited() const                     { return _can_be_preinited; }
224   bool has_done_preinit_check() const               { return _has_done_preinit_check; }
225 
226   void set_can_be_preinited(bool v) {
227     _can_be_preinited = v;
228     _has_done_preinit_check = true;
229   }
230   void reset_preinit_check() {
231     _can_be_preinited = false;
232     _has_done_preinit_check = false;
233   }
234 
235   size_t runtime_info_bytesize() const;
236 };
237 
238 template <typename T>
239 inline unsigned DumpTimeSharedClassTable_hash(T* const& k) {
240   if (CDSConfig::is_dumping_static_archive()) {
241     // Deterministic archive contents
242     uintx delta = k->name() - MetaspaceShared::symbol_rs_base();
243     return primitive_hash<uintx>(delta);
244   } else {
245     // Deterministic archive is not possible because classes can be loaded
246     // in multiple threads.
247     return primitive_hash<T*>(k);
248   }
249 }
250 
251 using DumpTimeSharedClassTableBaseType = ResourceHashtable<
252   InstanceKlass*,
253   DumpTimeClassInfo,
254   15889, // prime number
255   AnyObj::C_HEAP,
256   mtClassShared,
257   &DumpTimeSharedClassTable_hash>;
258 
259 class DumpTimeSharedClassTable: public DumpTimeSharedClassTableBaseType
260 {
261   int _builtin_count;
262   int _unregistered_count;
263 public:
264   DumpTimeSharedClassTable() {
265     _builtin_count = 0;
266     _unregistered_count = 0;
267   }
268   DumpTimeClassInfo* allocate_info(InstanceKlass* k);
269   DumpTimeClassInfo* get_info(InstanceKlass* k);
270   void inc_builtin_count()      { _builtin_count++; }
271   void inc_unregistered_count() { _unregistered_count++; }
272   void update_counts();
273   int count_of(bool is_builtin) const {
274     if (is_builtin) {
275       return _builtin_count;
276     } else {
277       return _unregistered_count;
278     }
279   }
280 
281   template<class ITER> void iterate_all_live_classes(ITER* iter) const;
282   template<typename Function> void iterate_all_live_classes(Function function) const;
283 
284 private:
285   // It's unsafe to iterate on classes whose loader is dead.
286   // Declare these private and don't implement them. This forces users of
287   // DumpTimeSharedClassTable to use the iterate_all_live_classes() methods
288   // instead.
289   template<class ITER> void iterate(ITER* iter) const;
290   template<typename Function> void iterate(Function function) const;
291   template<typename Function> void iterate_all(Function function) const;
292 };
293 
294 #endif // SHARE_CDS_DUMPTIMECLASSINFO_HPP