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