1 #ifdef USE_PRAGMA_IDENT_SRC 2 #pragma ident "@(#)vmSymbols.cpp 1.29 07/07/19 19:08:29 JVM" 3 #endif 4 /* 5 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. 6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7 * 8 * This code is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License version 2 only, as 10 * published by the Free Software Foundation. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 23 * CA 95054 USA or visit www.sun.com if you need additional information or 24 * have any questions. 25 * 26 */ 27 28 # include "incls/_precompiled.incl" 29 # include "incls/_vmSymbols.cpp.incl" 30 31 32 symbolOop vmSymbols::_symbols[vmSymbols::SID_LIMIT]; 33 34 symbolOop vmSymbols::_type_signatures[T_VOID+1] = { NULL /*, NULL...*/ }; 35 36 inline int compare_symbol(symbolOop a, symbolOop b) { 37 if (a == b) return 0; 38 // follow the natural address order: 39 return (address)a > (address)b ? +1 : -1; 40 } 41 42 static vmSymbols::SID vm_symbol_index[vmSymbols::SID_LIMIT]; 43 extern "C" { 44 static int compare_vmsymbol_sid(const void* void_a, const void* void_b) { 45 symbolOop a = vmSymbols::symbol_at(*((vmSymbols::SID*) void_a)); 46 symbolOop b = vmSymbols::symbol_at(*((vmSymbols::SID*) void_b)); 47 return compare_symbol(a, b); 48 } 49 } 50 51 #ifndef PRODUCT 52 #define VM_SYMBOL_ENUM_NAME_BODY(name, string) #name "\0" 53 static const char* vm_symbol_enum_names = 54 VM_SYMBOLS_DO(VM_SYMBOL_ENUM_NAME_BODY, VM_ALIAS_IGNORE) 55 "\0"; 56 static const char* vm_symbol_enum_name(vmSymbols::SID sid) { 57 const char* string = &vm_symbol_enum_names[0]; 58 int skip = (int)sid - (int)vmSymbols::FIRST_SID; 59 for (; skip != 0; skip--) { 60 size_t skiplen = strlen(string); 61 if (skiplen == 0) return "<unknown>"; // overflow 62 string += skiplen+1; 63 } 64 return string; 65 } 66 #endif //PRODUCT 67 68 // Put all the VM symbol strings in one place. 69 // Makes for a more compact libjvm. 70 #define VM_SYMBOL_BODY(name, string) string "\0" 71 static const char* vm_symbol_bodies = VM_SYMBOLS_DO(VM_SYMBOL_BODY, VM_ALIAS_IGNORE); 72 73 void vmSymbols::initialize(TRAPS) { 74 assert((int)SID_LIMIT <= (1<<log2_SID_LIMIT), "must fit in this bitfield"); 75 assert((int)SID_LIMIT*5 > (1<<log2_SID_LIMIT), "make the bitfield smaller, please"); 76 77 if (!UseSharedSpaces) { 78 const char* string = &vm_symbol_bodies[0]; 79 for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { 80 symbolOop sym = oopFactory::new_symbol(string, CHECK); 81 _symbols[index] = sym; 82 string += strlen(string); // skip string body 83 string += 1; // skip trailing null 84 } 85 86 _type_signatures[T_BYTE] = byte_signature(); 87 _type_signatures[T_CHAR] = char_signature(); 88 _type_signatures[T_DOUBLE] = double_signature(); 89 _type_signatures[T_FLOAT] = float_signature(); 90 _type_signatures[T_INT] = int_signature(); 91 _type_signatures[T_LONG] = long_signature(); 92 _type_signatures[T_SHORT] = short_signature(); 93 _type_signatures[T_BOOLEAN] = bool_signature(); 94 _type_signatures[T_VOID] = void_signature(); 95 // no single signatures for T_OBJECT or T_ARRAY 96 } 97 98 #ifdef ASSERT 99 // Check for duplicates: 100 for (int i1 = (int)FIRST_SID; i1 < (int)SID_LIMIT; i1++) { 101 symbolOop sym = symbol_at((SID)i1); 102 for (int i2 = (int)FIRST_SID; i2 < i1; i2++) { 103 if (symbol_at((SID)i2) == sym) { 104 tty->print("*** Duplicate VM symbol SIDs %s(%d) and %s(%d): \"", 105 vm_symbol_enum_name((SID)i2), i2, 106 vm_symbol_enum_name((SID)i1), i1); 107 sym->print_symbol_on(tty); 108 tty->print_cr("\""); 109 } 110 } 111 } 112 #endif //ASSERT 113 114 // Create an index for find_id: 115 { 116 for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { 117 vm_symbol_index[index] = (SID)index; 118 } 119 int num_sids = SID_LIMIT-FIRST_SID; 120 qsort(&vm_symbol_index[FIRST_SID], num_sids, sizeof(vm_symbol_index[0]), 121 compare_vmsymbol_sid); 122 } 123 124 #ifdef ASSERT 125 { 126 // Spot-check correspondence between strings, symbols, and enums: 127 assert(_symbols[NO_SID] == NULL, "must be"); 128 const char* str = "java/lang/Object"; 129 symbolOop sym = oopFactory::new_symbol(str, CHECK); 130 assert(strcmp(str, (char*)sym->base()) == 0, ""); 131 assert(sym == java_lang_Object(), ""); 132 SID sid = VM_SYMBOL_ENUM_NAME(java_lang_Object); 133 assert(find_sid(sym) == sid, ""); 134 assert(symbol_at(sid) == sym, ""); 135 136 // Make sure find_sid produces the right answer in each case. 137 for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { 138 sym = symbol_at((SID)index); 139 sid = find_sid(sym); 140 assert(sid == (SID)index, "symbol index works"); 141 // Note: If there are duplicates, this assert will fail. 142 // A "Duplicate VM symbol" message will have already been printed. 143 } 144 145 // The string "format" happens (at the moment) not to be a vmSymbol, 146 // though it is a method name in java.lang.String. 147 str = "format"; 148 sym = oopFactory::new_symbol(str, CHECK); 149 sid = find_sid(sym); 150 assert(sid == NO_SID, "symbol index works (negative test)"); 151 } 152 #endif 153 } 154 155 156 #ifndef PRODUCT 157 const char* vmSymbols::name_for(vmSymbols::SID sid) { 158 if (sid == NO_SID) 159 return "NO_SID"; 160 const char* string = &vm_symbol_bodies[0]; 161 for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { 162 if (index == (int)sid) 163 return string; 164 string += strlen(string); // skip string body 165 string += 1; // skip trailing null 166 } 167 return "BAD_SID"; 168 } 169 #endif 170 171 172 173 void vmSymbols::oops_do(OopClosure* f, bool do_all) { 174 for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { 175 f->do_oop((oop*) &_symbols[index]); 176 } 177 for (int i = 0; i < T_VOID+1; i++) { 178 if (_type_signatures[i] != NULL) { 179 assert(i >= T_BOOLEAN, "checking"); 180 f->do_oop((oop*)&_type_signatures[i]); 181 } else if (do_all) { 182 f->do_oop((oop*)&_type_signatures[i]); 183 } 184 } 185 } 186 187 188 BasicType vmSymbols::signature_type(symbolOop s) { 189 assert(s != NULL, "checking"); 190 for (int i = T_BOOLEAN; i < T_VOID+1; i++) { 191 if (s == _type_signatures[i]) { 192 return (BasicType)i; 193 } 194 } 195 return T_OBJECT; 196 } 197 198 199 static int mid_hint = (int)vmSymbols::FIRST_SID+1; 200 201 #ifndef PRODUCT 202 static int find_sid_calls, find_sid_probes; 203 // (Typical counts are calls=7000 and probes=17000.) 204 #endif 205 206 vmSymbols::SID vmSymbols::find_sid(symbolOop symbol) { 207 // Handle the majority of misses by a bounds check. 208 // Then, use a binary search over the index. 209 // Expected trip count is less than log2_SID_LIMIT, about eight. 210 // This is slow but acceptable, given that calls are not 211 // dynamically common. (methodOop::intrinsic_id has a cache.) 212 NOT_PRODUCT(find_sid_calls++); 213 int min = (int)FIRST_SID, max = (int)SID_LIMIT - 1; 214 SID sid = NO_SID, sid1; 215 int cmp1; 216 sid1 = vm_symbol_index[min]; 217 cmp1 = compare_symbol(symbol, symbol_at(sid1)); 218 if (cmp1 <= 0) { // before the first 219 if (cmp1 == 0) sid = sid1; 220 } else { 221 sid1 = vm_symbol_index[max]; 222 cmp1 = compare_symbol(symbol, symbol_at(sid1)); 223 if (cmp1 >= 0) { // after the last 224 if (cmp1 == 0) sid = sid1; 225 } else { 226 // After checking the extremes, do a binary search. 227 ++min; --max; // endpoints are done 228 int mid = mid_hint; // start at previous success 229 while (max >= min) { 230 assert(mid >= min && mid <= max, ""); 231 NOT_PRODUCT(find_sid_probes++); 232 sid1 = vm_symbol_index[mid]; 233 cmp1 = compare_symbol(symbol, symbol_at(sid1)); 234 if (cmp1 == 0) { 235 mid_hint = mid; 236 sid = sid1; 237 break; 238 } 239 if (cmp1 < 0) 240 max = mid - 1; // symbol < symbol_at(sid) 241 else 242 min = mid + 1; 243 244 // Pick a new probe point: 245 mid = (max + min) / 2; 246 } 247 } 248 } 249 250 #ifdef ASSERT 251 // Perform the exhaustive self-check the first 1000 calls, 252 // and every 100 calls thereafter. 253 static int find_sid_check_count = -2000; 254 if ((uint)++find_sid_check_count > (uint)100) { 255 if (find_sid_check_count > 0) find_sid_check_count = 0; 256 257 // Make sure this is the right answer, using linear search. 258 // (We have already proven that there are no duplicates in the list.) 259 SID sid2 = NO_SID; 260 for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { 261 symbolOop sym2 = symbol_at((SID)index); 262 if (sym2 == symbol) { 263 sid2 = (SID)index; 264 break; 265 } 266 } 267 // Unless it's a duplicate, assert that the sids are the same. 268 if (_symbols[sid] != _symbols[sid2]) { 269 assert(sid == sid2, "binary same as linear search"); 270 } 271 } 272 #endif //ASSERT 273 274 return sid; 275 } 276 277 278 #define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0" 279 static const char* vm_intrinsic_name_bodies = 280 VM_INTRINSICS_DO(VM_INTRINSIC_INITIALIZE, 281 VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); 282 283 static const char* vm_intrinsic_name_table[vmIntrinsics::ID_LIMIT]; 284 285 const char* vmIntrinsics::name_at(vmIntrinsics::ID id) { 286 const char** nt = &vm_intrinsic_name_table[0]; 287 if (nt[_none] == NULL) { 288 char* string = (char*) &vm_intrinsic_name_bodies[0]; 289 for (int index = FIRST_ID; index < ID_LIMIT; index++) { 290 nt[index] = string; 291 string += strlen(string); // skip string body 292 string += 1; // skip trailing null 293 } 294 assert(!strcmp(nt[_hashCode], "_hashCode"), "lined up"); 295 nt[_none] = "_none"; 296 } 297 if ((uint)id < (uint)ID_LIMIT) 298 return vm_intrinsic_name_table[(uint)id]; 299 else 300 return "(unknown intrinsic)"; 301 } 302 303 // These are flag-matching functions: 304 inline bool match_F_R(jshort flags) { 305 const int req = 0; 306 const int neg = JVM_ACC_STATIC | JVM_ACC_SYNCHRONIZED; 307 return (flags & (req | neg)) == req; 308 } 309 inline bool match_F_RN(jshort flags) { 310 const int req = JVM_ACC_NATIVE; 311 const int neg = JVM_ACC_STATIC | JVM_ACC_SYNCHRONIZED; 312 return (flags & (req | neg)) == req; 313 } 314 inline bool match_F_S(jshort flags) { 315 const int req = JVM_ACC_STATIC; 316 const int neg = JVM_ACC_SYNCHRONIZED; 317 return (flags & (req | neg)) == req; 318 } 319 inline bool match_F_SN(jshort flags) { 320 const int req = JVM_ACC_STATIC | JVM_ACC_NATIVE; 321 const int neg = JVM_ACC_SYNCHRONIZED; 322 return (flags & (req | neg)) == req; 323 } 324 325 // These are for forming case labels: 326 #define ID3(x, y, z) (( jint)(z) + \ 327 ((jint)(y) << vmSymbols::log2_SID_LIMIT) + \ 328 ((jint)(x) << (2*vmSymbols::log2_SID_LIMIT)) ) 329 #define SID_ENUM(n) vmSymbols::VM_SYMBOL_ENUM_NAME(n) 330 331 vmIntrinsics::ID vmIntrinsics::find_id(vmSymbols::SID holder, 332 vmSymbols::SID name, 333 vmSymbols::SID sig, 334 jshort flags) { 335 assert((int)vmSymbols::SID_LIMIT <= (1<<vmSymbols::log2_SID_LIMIT), "must fit"); 336 337 // Let the C compiler build the decision tree. 338 339 #define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ 340 case ID3(SID_ENUM(klass), SID_ENUM(name), SID_ENUM(sig)): \ 341 if (!match_##fcode(flags)) break; \ 342 return id; 343 344 switch (ID3(holder, name, sig)) { 345 VM_INTRINSICS_DO(VM_INTRINSIC_CASE, 346 VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); 347 } 348 return vmIntrinsics::_none; 349 350 #undef VM_INTRINSIC_CASE 351 } 352 353 354 const char* vmIntrinsics::short_name_as_C_string(vmIntrinsics::ID id, char* buf, int buflen) { 355 const char* str = name_at(id); 356 #ifndef PRODUCT 357 const char* kname = vmSymbols::name_for(class_for(id)); 358 const char* mname = vmSymbols::name_for(name_for(id)); 359 const char* sname = vmSymbols::name_for(signature_for(id)); 360 const char* fname = ""; 361 switch (flags_for(id)) { 362 case F_RN: fname = "native "; break; 363 case F_SN: fname = "native static "; break; 364 case F_S: fname = "static "; break; 365 } 366 const char* kptr = strrchr(kname, '/'); 367 if (kptr != NULL) kname = kptr + 1; 368 int len = jio_snprintf(buf, buflen, "%s: %s%s.%s%s", 369 str, fname, kname, mname, sname); 370 if (len < buflen) 371 str = buf; 372 #endif //PRODUCT 373 return str; 374 } 375 376 377 // These are for friendly printouts of intrinsics: 378 379 vmSymbols::SID vmIntrinsics::class_for(vmIntrinsics::ID id) { 380 #ifndef PRODUCT 381 #define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ 382 case id: return SID_ENUM(klass); 383 384 switch (id) { 385 VM_INTRINSICS_DO(VM_INTRINSIC_CASE, 386 VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); 387 } 388 #undef VM_INTRINSIC_CASE 389 #endif //PRODUCT 390 return vmSymbols::NO_SID; 391 } 392 393 vmSymbols::SID vmIntrinsics::name_for(vmIntrinsics::ID id) { 394 #ifndef PRODUCT 395 #define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ 396 case id: return SID_ENUM(name); 397 398 switch (id) { 399 VM_INTRINSICS_DO(VM_INTRINSIC_CASE, 400 VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); 401 } 402 #undef VM_INTRINSIC_CASE 403 #endif //PRODUCT 404 return vmSymbols::NO_SID; 405 } 406 407 vmSymbols::SID vmIntrinsics::signature_for(vmIntrinsics::ID id) { 408 #ifndef PRODUCT 409 #define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ 410 case id: return SID_ENUM(sig); 411 412 switch (id) { 413 VM_INTRINSICS_DO(VM_INTRINSIC_CASE, 414 VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); 415 } 416 #undef VM_INTRINSIC_CASE 417 #endif //PRODUCT 418 return vmSymbols::NO_SID; 419 } 420 421 vmIntrinsics::Flags vmIntrinsics::flags_for(vmIntrinsics::ID id) { 422 #ifndef PRODUCT 423 #define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ 424 case id: return fcode; 425 426 switch (id) { 427 VM_INTRINSICS_DO(VM_INTRINSIC_CASE, 428 VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); 429 } 430 #undef VM_INTRINSIC_CASE 431 #endif //PRODUCT 432 return F_none; 433 } 434 435 436 #ifndef PRODUCT 437 // verify_method performs an extra check on a matched intrinsic method 438 439 static bool match_method(methodOop m, symbolOop n, symbolOop s) { 440 return (m->name() == n && 441 m->signature() == s); 442 } 443 444 static vmIntrinsics::ID match_method_with_klass(methodOop m, symbolOop mk) { 445 #define VM_INTRINSIC_MATCH(id, klassname, namepart, sigpart, flags) \ 446 { symbolOop k = vmSymbols::klassname(); \ 447 if (mk == k) { \ 448 symbolOop n = vmSymbols::namepart(); \ 449 symbolOop s = vmSymbols::sigpart(); \ 450 if (match_method(m, n, s)) \ 451 return vmIntrinsics::id; \ 452 } } 453 VM_INTRINSICS_DO(VM_INTRINSIC_MATCH, 454 VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); 455 return vmIntrinsics::_none; 456 #undef VM_INTRINSIC_MATCH 457 } 458 459 void vmIntrinsics::verify_method(ID actual_id, methodOop m) { 460 symbolOop mk = Klass::cast(m->method_holder())->name(); 461 ID declared_id = match_method_with_klass(m, mk); 462 463 if (declared_id == actual_id) return; // success 464 465 if (declared_id == _none && actual_id != _none && mk == vmSymbols::java_lang_StrictMath()) { 466 // Here are a few special cases in StrictMath not declared in vmSymbols.hpp. 467 switch (actual_id) { 468 case _min: 469 case _max: 470 case _dsqrt: 471 declared_id = match_method_with_klass(m, vmSymbols::java_lang_Math()); 472 if (declared_id == actual_id) return; // acceptable alias 473 break; 474 } 475 } 476 477 const char* declared_name = name_at(declared_id); 478 const char* actual_name = name_at(actual_id); 479 methodHandle mh = m; 480 m = NULL; 481 ttyLocker ttyl; 482 if (xtty != NULL) { 483 xtty->begin_elem("intrinsic_misdeclared actual='%s' declared='%s'", 484 actual_name, declared_name); 485 xtty->method(mh); 486 xtty->end_elem(""); 487 } 488 if (PrintMiscellaneous && (WizardMode || Verbose)) { 489 tty->print_cr("*** misidentified method; %s(%d) should be %s(%d):", 490 declared_name, declared_id, actual_name, actual_id); 491 m->print_short_name(tty); 492 tty->cr(); 493 } 494 } 495 #endif //PRODUCT