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 }