1 /* 2 * Copyright (c) 1997, 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 #include "cds/cdsConfig.hpp" 26 #include "cds/serializeClosure.hpp" 27 #include "classfile/symbolTable.hpp" 28 #include "classfile/vmSymbols.hpp" 29 #include "compiler/compilerDirectives.hpp" 30 #include "jvm.h" 31 #include "memory/allocation.inline.hpp" 32 #include "memory/oopFactory.hpp" 33 #include "memory/metaspaceClosure.hpp" 34 #include "oops/oop.inline.hpp" 35 #include "runtime/handles.inline.hpp" 36 #include "runtime/signature.hpp" 37 #include "utilities/xmlstream.hpp" 38 39 40 Symbol* vmSymbols::_type_signatures[T_VOID+1] = { nullptr /*, nullptr...*/ }; 41 42 inline int compare_symbol(const Symbol* a, const Symbol* b) { 43 if (a == b) return 0; 44 // follow the natural address order: 45 return (address)a > (address)b ? +1 : -1; 46 } 47 48 static vmSymbolID vm_symbol_index[vmSymbols::number_of_symbols()]; 49 extern "C" { 50 static int compare_vmsymbol_sid(const void* void_a, const void* void_b) { 51 const Symbol* a = Symbol::vm_symbol_at(*((vmSymbolID*) void_a)); 52 const Symbol* b = Symbol::vm_symbol_at(*((vmSymbolID*) void_b)); 53 return compare_symbol(a, b); 54 } 55 } 56 57 #ifdef ASSERT 58 #define VM_SYMBOL_ENUM_NAME_BODY(name, string) #name "\0" 59 static const char* vm_symbol_enum_names = 60 VM_SYMBOLS_DO(VM_SYMBOL_ENUM_NAME_BODY, VM_ALIAS_IGNORE) 61 "\0"; 62 static const char* vm_symbol_enum_name(vmSymbolID sid) { 63 const char* string = &vm_symbol_enum_names[0]; 64 int skip = vmSymbols::as_int(sid) - vmSymbols::as_int(vmSymbolID::FIRST_SID); 65 for (; skip != 0; skip--) { 66 size_t skiplen = strlen(string); 67 if (skiplen == 0) return "<unknown>"; // overflow 68 string += skiplen+1; 69 } 70 return string; 71 } 72 #endif //ASSERT 73 74 // Put all the VM symbol strings in one place. 75 // Makes for a more compact libjvm. 76 #define VM_SYMBOL_BODY(name, string) string "\0" 77 static const char* vm_symbol_bodies = VM_SYMBOLS_DO(VM_SYMBOL_BODY, VM_ALIAS_IGNORE); 78 79 void vmSymbols::initialize() { 80 assert(SID_LIMIT <= (1<<log2_SID_LIMIT), "must fit in this bitfield"); 81 assert(SID_LIMIT*5 > (1<<log2_SID_LIMIT), "make the bitfield smaller, please"); 82 assert(vmIntrinsics::FLAG_LIMIT <= (1 << vmIntrinsics::log2_FLAG_LIMIT), "must fit in this bitfield"); 83 84 if (!CDSConfig::is_using_archive()) { 85 const char* string = &vm_symbol_bodies[0]; 86 for (auto index : EnumRange<vmSymbolID>{}) { 87 Symbol* sym = SymbolTable::new_permanent_symbol(string); 88 Symbol::_vm_symbols[as_int(index)] = sym; 89 string += strlen(string); // skip string body 90 string += 1; // skip trailing null 91 } 92 93 _type_signatures[T_BYTE] = byte_signature(); 94 _type_signatures[T_CHAR] = char_signature(); 95 _type_signatures[T_DOUBLE] = double_signature(); 96 _type_signatures[T_FLOAT] = float_signature(); 97 _type_signatures[T_INT] = int_signature(); 98 _type_signatures[T_LONG] = long_signature(); 99 _type_signatures[T_SHORT] = short_signature(); 100 _type_signatures[T_BOOLEAN] = bool_signature(); 101 _type_signatures[T_VOID] = void_signature(); 102 #ifdef ASSERT 103 for (int i = (int)T_BOOLEAN; i < (int)T_VOID+1; i++) { 104 Symbol* s = _type_signatures[i]; 105 if (s == nullptr) continue; 106 SignatureStream ss(s, false); 107 assert(ss.type() == i, "matching signature"); 108 assert(!ss.is_reference(), "no single-char signature for T_OBJECT, etc."); 109 } 110 #endif 111 } 112 113 initialize_migrated_class_names(); 114 115 #ifdef ASSERT 116 // Check for duplicates: 117 118 for (auto i1 : EnumRange<vmSymbolID>{}) { 119 Symbol* sym = symbol_at(i1); 120 for (auto i2 : EnumRange<vmSymbolID>{vmSymbolID::FIRST_SID, i1}) { 121 if (i2 != i1 && symbol_at(i2) == sym) { 122 tty->print("*** Duplicate VM symbol SIDs %s(%d) and %s(%d): \"", 123 vm_symbol_enum_name(i2), as_int(i2), 124 vm_symbol_enum_name(i1), as_int(i1)); 125 sym->print_symbol_on(tty); 126 tty->print_cr("\""); 127 } 128 } 129 } 130 #endif //ASSERT 131 132 // Create an index for find_id: 133 { 134 for (auto index : EnumRange<vmSymbolID>{}) { 135 vm_symbol_index[as_int(index)] = index; 136 } 137 int num_sids = SID_LIMIT-FIRST_SID; 138 qsort(&vm_symbol_index[FIRST_SID], num_sids, sizeof(vm_symbol_index[0]), 139 compare_vmsymbol_sid); 140 } 141 142 #ifdef ASSERT 143 { 144 // Spot-check correspondence between strings, symbols, and enums: 145 assert(Symbol::_vm_symbols[NO_SID] == nullptr, "must be"); 146 const char* str = "java/lang/Object"; 147 TempNewSymbol jlo = SymbolTable::new_permanent_symbol(str); 148 assert(strncmp(str, (char*)jlo->base(), jlo->utf8_length()) == 0, ""); 149 assert(jlo == java_lang_Object(), ""); 150 vmSymbolID sid = VM_SYMBOL_ENUM_NAME(java_lang_Object); 151 assert(find_sid(jlo) == sid, ""); 152 assert(symbol_at(sid) == jlo, ""); 153 154 // Make sure find_sid produces the right answer in each case. 155 for (auto index : EnumRange<vmSymbolID>{}) { 156 Symbol* sym = symbol_at(index); 157 sid = find_sid(sym); 158 assert(sid == index, "symbol index works"); 159 // Note: If there are duplicates, this assert will fail. 160 // A "Duplicate VM symbol" message will have already been printed. 161 } 162 163 // The string "format" happens (at the moment) not to be a vmSymbol, 164 // though it is a method name in java.lang.String. 165 str = "format"; 166 TempNewSymbol fmt = SymbolTable::new_permanent_symbol(str); 167 sid = find_sid(fmt); 168 assert(sid == vmSymbolID::NO_SID, "symbol index works (negative test)"); 169 } 170 #endif 171 } 172 173 174 #ifndef PRODUCT 175 const char* vmSymbols::name_for(vmSymbolID sid) { 176 if (sid == vmSymbolID::NO_SID) 177 return "NO_SID"; 178 const char* string = &vm_symbol_bodies[0]; 179 for (auto index : EnumRange<vmSymbolID>{}) { 180 if (index == sid) 181 return string; 182 string += strlen(string); // skip string body 183 string += 1; // skip trailing null 184 } 185 return "BAD_SID"; 186 } 187 #endif 188 189 190 191 void vmSymbols::symbols_do(SymbolClosure* f) { 192 for (auto index : EnumRange<vmSymbolID>{}) { 193 f->do_symbol(&Symbol::_vm_symbols[as_int(index)]); 194 } 195 for (int i = 0; i < T_VOID+1; i++) { 196 f->do_symbol(&_type_signatures[i]); 197 } 198 } 199 200 void vmSymbols::metaspace_pointers_do(MetaspaceClosure *closure) { 201 for (auto index : EnumRange<vmSymbolID>{}) { 202 closure->push(&Symbol::_vm_symbols[as_int(index)]); 203 } 204 for (int i = 0; i < T_VOID+1; i++) { 205 closure->push(&_type_signatures[i]); 206 } 207 } 208 209 void vmSymbols::serialize(SerializeClosure* soc) { 210 soc->do_ptrs((void**)&Symbol::_vm_symbols[FIRST_SID], 211 (SID_LIMIT - FIRST_SID) * sizeof(Symbol::_vm_symbols[0])); 212 soc->do_ptrs((void**)_type_signatures, sizeof(_type_signatures)); 213 } 214 215 #ifndef PRODUCT 216 static uint find_sid_calls, find_sid_probes; 217 // (Typical counts are calls=7000 and probes=17000.) 218 #endif 219 220 vmSymbolID vmSymbols::find_sid(const Symbol* symbol) { 221 static int mid_hint = FIRST_SID+1; 222 // Handle the majority of misses by a bounds check. 223 // Then, use a binary search over the index. 224 // Expected trip count is less than log2_SID_LIMIT, about eight. 225 // This is slow but acceptable, given that calls are not 226 // dynamically common. (Method*::intrinsic_id has a cache.) 227 NOT_PRODUCT(find_sid_calls++); 228 int min = FIRST_SID, max = SID_LIMIT - 1; 229 vmSymbolID sid = vmSymbolID::NO_SID, sid1; 230 int cmp1; 231 sid1 = vm_symbol_index[min]; 232 cmp1 = compare_symbol(symbol, Symbol::vm_symbol_at(sid1)); 233 if (cmp1 <= 0) { // before the first 234 if (cmp1 == 0) sid = sid1; 235 } else { 236 sid1 = vm_symbol_index[max]; 237 cmp1 = compare_symbol(symbol, symbol_at(sid1)); 238 if (cmp1 >= 0) { // after the last 239 if (cmp1 == 0) sid = sid1; 240 } else { 241 // After checking the extremes, do a binary search. 242 ++min; --max; // endpoints are done 243 int mid = mid_hint; // start at previous success 244 while (max >= min) { 245 assert(mid >= min && mid <= max, ""); 246 NOT_PRODUCT(find_sid_probes++); 247 sid1 = vm_symbol_index[mid]; 248 cmp1 = compare_symbol(symbol, symbol_at(sid1)); 249 if (cmp1 == 0) { 250 mid_hint = mid; 251 sid = sid1; 252 break; 253 } 254 if (cmp1 < 0) 255 max = mid - 1; // symbol < symbol_at(sid) 256 else 257 min = mid + 1; 258 259 // Pick a new probe point: 260 mid = (max + min) / 2; 261 } 262 } 263 } 264 265 #ifdef ASSERT 266 if (sid == vmSymbolID::NO_SID) { 267 return sid; 268 } 269 270 // Perform the exhaustive self-check the first 1000 calls, 271 // and every 100 calls thereafter. 272 static int find_sid_check_count = -2000; 273 if ((uint)++find_sid_check_count > (uint)100) { 274 if (find_sid_check_count > 0) find_sid_check_count = 0; 275 276 // Make sure this is the right answer, using linear search. 277 // (We have already proven that there are no duplicates in the list.) 278 vmSymbolID sid2 = vmSymbolID::NO_SID; 279 for (auto index : EnumRange<vmSymbolID>{}) { 280 Symbol* sym2 = symbol_at(index); 281 if (sym2 == symbol) { 282 sid2 = index; 283 break; 284 } 285 } 286 // Unless it's a duplicate, assert that the sids are the same. 287 if (Symbol::_vm_symbols[as_int(sid)] != Symbol::_vm_symbols[as_int(sid2)]) { 288 assert(sid == sid2, "binary same as linear search"); 289 } 290 } 291 #endif //ASSERT 292 293 return sid; 294 } 295 296 vmSymbolID vmSymbols::find_sid(const char* symbol_name) { 297 Symbol* symbol = SymbolTable::probe(symbol_name, (int) strlen(symbol_name)); 298 if (symbol == nullptr) return vmSymbolID::NO_SID; 299 return find_sid(symbol); 300 } 301 302 // The list of these migrated value classes is in 303 // open/make/modules/java.base/gensrc/GensrcValueClasses.gmk. 304 305 Symbol* vmSymbols::_migrated_class_names[_migrated_class_names_length]; 306 307 void vmSymbols::initialize_migrated_class_names() { 308 int i = 0; 309 _migrated_class_names[i++] = java_lang_Byte(); 310 _migrated_class_names[i++] = java_lang_Short(); 311 _migrated_class_names[i++] = java_lang_Integer(); 312 _migrated_class_names[i++] = java_lang_Long(); 313 _migrated_class_names[i++] = java_lang_Float(); 314 _migrated_class_names[i++] = java_lang_Double(); 315 _migrated_class_names[i++] = java_lang_Boolean(); 316 _migrated_class_names[i++] = java_lang_Character(); 317 _migrated_class_names[i++] = java_lang_Number(); 318 _migrated_class_names[i++] = java_lang_Record(); 319 _migrated_class_names[i++] = java_util_Optional(); 320 _migrated_class_names[i++] = java_util_OptionalInt(); 321 _migrated_class_names[i++] = java_util_OptionalLong(); 322 _migrated_class_names[i++] = java_util_OptionalDouble(); 323 _migrated_class_names[i++] = java_time_LocalDate(); 324 _migrated_class_names[i++] = java_time_LocalDateTime(); 325 _migrated_class_names[i++] = java_time_LocalTime(); 326 _migrated_class_names[i++] = java_time_Duration(); 327 _migrated_class_names[i++] = java_time_Instant(); 328 _migrated_class_names[i++] = java_time_MonthDay(); 329 _migrated_class_names[i++] = java_time_ZonedDateTime(); 330 _migrated_class_names[i++] = java_time_OffsetDateTime(); 331 _migrated_class_names[i++] = java_time_OffsetTime(); 332 _migrated_class_names[i++] = java_time_YearMonth(); 333 _migrated_class_names[i++] = java_time_Year(); 334 _migrated_class_names[i++] = java_time_Period(); 335 _migrated_class_names[i++] = java_time_chrono_ChronoLocalDateImpl(); 336 _migrated_class_names[i++] = java_time_chrono_MinguoDate(); 337 _migrated_class_names[i++] = java_time_chrono_HijrahDate(); 338 _migrated_class_names[i++] = java_time_chrono_JapaneseDate(); 339 _migrated_class_names[i++] = java_time_chrono_ThaiBuddhistDate(); 340 assert(i == _migrated_class_names_length, "should be"); 341 }