1 /*
  2  * Copyright (c) 2021, 2025, 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_RUNTIMECLASSINFO_HPP
 26 #define SHARE_CDS_RUNTIMECLASSINFO_HPP
 27 
 28 #include "cds/archiveBuilder.hpp"
 29 #include "cds/archiveUtils.hpp"
 30 #include "cds/cds_globals.hpp"
 31 #include "cds/metaspaceShared.hpp"
 32 #include "classfile/compactHashtable.hpp"
 33 #include "classfile/javaClasses.hpp"
 34 #include "memory/metaspaceClosure.hpp"
 35 #include "oops/instanceKlass.hpp"
 36 #include "prims/jvmtiExport.hpp"
 37 #include "utilities/growableArray.hpp"
 38 
 39 class DumpTimeClassInfo;
 40 class Method;
 41 class Symbol;
 42 
 43 class RunTimeClassInfo {
 44  public:
 45  enum : char {
 46     FROM_FIELD_IS_PROTECTED = 1 << 0,
 47     FROM_IS_ARRAY           = 1 << 1,
 48     FROM_IS_OBJECT          = 1 << 2
 49   };
 50 
 51   struct CrcInfo {
 52     int _clsfile_size;
 53     int _clsfile_crc32;
 54   };
 55 
 56   // This is different than DumpTimeClassInfo::DTVerifierConstraint. We use
 57   // u4 instead of Symbol* to save space on 64-bit CPU.
 58   struct RTVerifierConstraint {
 59     u4 _name;
 60     u4 _from_name;
 61     Symbol* name() { return ArchiveUtils::offset_to_archived_address<Symbol*>(_name); }
 62     Symbol* from_name() { return ArchiveUtils::offset_to_archived_address<Symbol*>(_from_name); }
 63   };
 64 
 65   struct RTLoaderConstraint {
 66     u4   _name;
 67     char _loader_type1;
 68     char _loader_type2;
 69     Symbol* constraint_name() { return ArchiveUtils::offset_to_archived_address<Symbol*>(_name); }
 70   };
 71   struct RTEnumKlassStaticFields {
 72     int _num;
 73     int _root_indices[1];
 74   };
 75 
 76 private:
 77   u4 _klass_offset;
 78   u4 _nest_host_offset;
 79   int _num_verifier_constraints;
 80   int _num_loader_constraints;
 81 
 82   // optional CrcInfo                 _crc;  (only for UNREGISTERED classes)
 83   // optional InstanceKlass*          _nest_host
 84   // optional RTLoaderConstraint      _loader_constraint_types[_num_loader_constraints]
 85   // optional RTVerifierConstraint    _verifier_constraints[_num_verifier_constraints]
 86   // optional char                    _verifier_constraint_flags[_num_verifier_constraints]
 87   // optional RTEnumKlassStaticFields _enum_klass_static_fields;
 88 
 89   static size_t header_size_size() {
 90     return align_up(sizeof(RunTimeClassInfo), wordSize);
 91   }
 92   static size_t verifier_constraints_size(int num_verifier_constraints) {
 93     return align_up(sizeof(RTVerifierConstraint) * num_verifier_constraints, wordSize);
 94   }
 95   static size_t verifier_constraint_flags_size(int num_verifier_constraints) {
 96     return align_up(sizeof(char) * num_verifier_constraints, wordSize);
 97   }
 98   static size_t loader_constraints_size(int num_loader_constraints) {
 99     return align_up(sizeof(RTLoaderConstraint) * num_loader_constraints, wordSize);
100   }
101   static size_t enum_klass_static_fields_size(int num_fields) {
102     size_t size = num_fields <= 0 ? 0 : sizeof(RTEnumKlassStaticFields) + (num_fields - 1) * sizeof(int);
103     return align_up(size, wordSize);
104   }
105 
106   static size_t nest_host_size(InstanceKlass* klass) {
107     if (klass->is_hidden()) {
108       return sizeof(InstanceKlass*);
109     } else {
110       return 0;
111     }
112   }
113 
114   static size_t crc_size(InstanceKlass* klass);
115 public:
116   InstanceKlass* klass() const;
117   int num_verifier_constraints() const { return _num_verifier_constraints; }
118   int num_loader_constraints() const { return _num_loader_constraints; }
119   static size_t byte_size(InstanceKlass* klass, int num_verifier_constraints, int num_loader_constraints,
120                           int num_enum_klass_static_fields) {
121     return header_size_size() +
122            crc_size(klass) +
123            nest_host_size(klass) +
124            loader_constraints_size(num_loader_constraints) +
125            verifier_constraints_size(num_verifier_constraints) +
126            verifier_constraint_flags_size(num_verifier_constraints) +
127            enum_klass_static_fields_size(num_enum_klass_static_fields);
128   }
129 
130 private:
131   size_t crc_offset() const {
132     return header_size_size();
133   }
134 
135   size_t nest_host_offset() const {
136     return crc_offset() + crc_size(klass());
137   }
138 
139   size_t loader_constraints_offset() const  {
140     return nest_host_offset() + nest_host_size(klass());
141   }
142   size_t verifier_constraints_offset() const {
143     return loader_constraints_offset() + loader_constraints_size(_num_loader_constraints);
144   }
145   size_t verifier_constraint_flags_offset() const {
146     return verifier_constraints_offset() + verifier_constraints_size(_num_verifier_constraints);
147   }
148   size_t enum_klass_static_fields_offset() const {
149     return verifier_constraint_flags_offset() + verifier_constraint_flags_size(_num_verifier_constraints);
150   }
151 
152   void check_verifier_constraint_offset(int i) const {
153     assert(0 <= i && i < _num_verifier_constraints, "sanity");
154   }
155 
156   void check_loader_constraint_offset(int i) const {
157     assert(0 <= i && i < _num_loader_constraints, "sanity");
158   }
159 
160   RTEnumKlassStaticFields* enum_klass_static_fields_addr() const {
161     assert(klass()->has_archived_enum_objs(), "sanity");
162     return (RTEnumKlassStaticFields*)(address(this) + enum_klass_static_fields_offset());
163   }
164 
165 public:
166   CrcInfo* crc() const {
167     assert(crc_size(klass()) > 0, "must be");
168     return (CrcInfo*)(address(this) + crc_offset());
169   }
170   RTVerifierConstraint* verifier_constraints() {
171     assert(_num_verifier_constraints > 0, "sanity");
172     return (RTVerifierConstraint*)(address(this) + verifier_constraints_offset());
173   }
174   RTVerifierConstraint* verifier_constraint_at(int i) {
175     check_verifier_constraint_offset(i);
176     return verifier_constraints() + i;
177   }
178 
179   char* verifier_constraint_flags() {
180     assert(_num_verifier_constraints > 0, "sanity");
181     return (char*)(address(this) + verifier_constraint_flags_offset());
182   }
183 
184   InstanceKlass* nest_host() {
185     assert(!ArchiveBuilder::is_active(), "not called when dumping archive");
186     return ArchiveUtils::offset_to_archived_address_or_null<InstanceKlass*>(_nest_host_offset);
187   }
188 
189   RTLoaderConstraint* loader_constraints() {
190     assert(_num_loader_constraints > 0, "sanity");
191     return (RTLoaderConstraint*)(address(this) + loader_constraints_offset());
192   }
193 
194   RTLoaderConstraint* loader_constraint_at(int i) {
195     check_loader_constraint_offset(i);
196     return loader_constraints() + i;
197   }
198 
199   void init(DumpTimeClassInfo& info);
200 
201   bool matches(int clsfile_size, int clsfile_crc32) const {
202     return crc()->_clsfile_size  == clsfile_size &&
203            crc()->_clsfile_crc32 == clsfile_crc32;
204   }
205 
206   char verifier_constraint_flag(int i) {
207     check_verifier_constraint_offset(i);
208     return verifier_constraint_flags()[i];
209   }
210 
211   bool from_field_is_protected(int i) {
212     return (verifier_constraint_flag(i) & FROM_FIELD_IS_PROTECTED) != 0;
213   }
214 
215   bool from_is_array(int i) {
216     return (verifier_constraint_flag(i) & FROM_IS_ARRAY) != 0;
217   }
218   bool from_is_object(int i) {
219     return (verifier_constraint_flag(i) & FROM_IS_OBJECT) != 0;
220   }
221 
222   int num_enum_klass_static_fields(int i) const {
223     return enum_klass_static_fields_addr()->_num;
224   }
225 
226   void set_num_enum_klass_static_fields(int num) {
227     enum_klass_static_fields_addr()->_num = num;
228   }
229 
230   int enum_klass_static_field_root_index_at(int i) const {
231     assert(0 <= i && i < enum_klass_static_fields_addr()->_num, "must be");
232     return enum_klass_static_fields_addr()->_root_indices[i];
233   }
234 
235   void set_enum_klass_static_field_root_index_at(int i, int root_index) {
236     assert(0 <= i && i < enum_klass_static_fields_addr()->_num, "must be");
237     enum_klass_static_fields_addr()->_root_indices[i] = root_index;
238   }
239 private:
240   // ArchiveBuilder::make_shallow_copy() has reserved a pointer immediately
241   // before archived InstanceKlasses. We can use this slot to do a quick
242   // lookup of InstanceKlass* -> RunTimeClassInfo* without
243   // building a new hashtable.
244   //
245   //  info_pointer_addr(klass) --> 0x0100   RunTimeClassInfo*
246   //  InstanceKlass* klass     --> 0x0108   <C++ vtbl>
247   //                               0x0110   fields from Klass ...
248   static RunTimeClassInfo** info_pointer_addr(InstanceKlass* klass) {
249     return &((RunTimeClassInfo**)klass)[-1];
250   }
251 
252 public:
253   static RunTimeClassInfo* get_for(InstanceKlass* klass) {
254     assert(klass->is_shared(), "don't call for non-shared class");
255     return *info_pointer_addr(klass);
256   }
257   static void set_for(InstanceKlass* klass, RunTimeClassInfo* record) {
258     assert(ArchiveBuilder::current()->is_in_buffer_space(klass), "must be");
259     assert(ArchiveBuilder::current()->is_in_buffer_space(record), "must be");
260     *info_pointer_addr(klass) = record;
261     ArchivePtrMarker::mark_pointer(info_pointer_addr(klass));
262   }
263 
264   // Used by RunTimeSharedDictionary to implement OffsetCompactHashtable::EQUALS
265   static inline bool EQUALS(
266        const RunTimeClassInfo* value, Symbol* key, int len_unused) {
267     return (value->klass()->name() == key);
268   }
269 };
270 
271 class RunTimeSharedDictionary : public OffsetCompactHashtable<
272   Symbol*,
273   const RunTimeClassInfo*,
274   RunTimeClassInfo::EQUALS> {};
275 #endif // SHARE_CDS_RUNTIMECLASSINFO_HPP