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/metaspaceClosure.hpp"
33 #include "memory/oopFactory.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 }