| 1 | /* |
| 2 | * Copyright (c) 1997, 2019, 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 "precompiled.hpp" |
| 26 | #include "jvm.h" |
| 27 | #include "classfile/symbolTable.hpp" |
| 28 | #include "classfile/vmSymbols.hpp" |
| 29 | #include "compiler/compilerDirectives.hpp" |
| 30 | #include "memory/allocation.inline.hpp" |
| 31 | #include "memory/oopFactory.hpp" |
| 32 | #include "memory/metaspaceClosure.hpp" |
| 33 | #include "oops/oop.inline.hpp" |
| 34 | #include "runtime/handles.inline.hpp" |
| 35 | #include "utilities/xmlstream.hpp" |
| 36 | |
| 37 | |
| 38 | Symbol* vmSymbols::_symbols[vmSymbols::SID_LIMIT]; |
| 39 | |
| 40 | Symbol* vmSymbols::_type_signatures[T_VOID+1] = { NULL /*, NULL...*/ }; |
| 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 vmSymbols::SID vm_symbol_index[vmSymbols::SID_LIMIT]; |
| 49 | extern "C" { |
| 50 | static int compare_vmsymbol_sid(const void* void_a, const void* void_b) { |
| 51 | const Symbol* a = vmSymbols::symbol_at(*((vmSymbols::SID*) void_a)); |
| 52 | const Symbol* b = vmSymbols::symbol_at(*((vmSymbols::SID*) 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(vmSymbols::SID sid) { |
| 63 | const char* string = &vm_symbol_enum_names[0]; |
| 64 | int skip = (int)sid - (int)vmSymbols::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(TRAPS) { |
| 80 | assert((int)SID_LIMIT <= (1<<log2_SID_LIMIT), "must fit in this bitfield" ); |
| 81 | assert((int)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 (!UseSharedSpaces) { |
| 85 | const char* string = &vm_symbol_bodies[0]; |
| 86 | for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { |
| 87 | Symbol* sym = SymbolTable::new_permanent_symbol(string); |
| 88 | _symbols[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 | // no single signatures for T_OBJECT or T_ARRAY |
| 103 | #ifdef ASSERT |
| 104 | for (int i = (int)T_BOOLEAN; i < (int)T_VOID+1; i++) { |
| 105 | Symbol* s = _type_signatures[i]; |
| 106 | if (s == NULL) continue; |
| 107 | BasicType st = signature_type(s); |
| 108 | assert(st == i, "" ); |
| 109 | } |
| 110 | #endif |
| 111 | } |
| 112 | |
| 113 | #ifdef ASSERT |
| 114 | // Check for duplicates: |
| 115 | for (int i1 = (int)FIRST_SID; i1 < (int)SID_LIMIT; i1++) { |
| 116 | Symbol* sym = symbol_at((SID)i1); |
| 117 | for (int i2 = (int)FIRST_SID; i2 < i1; i2++) { |
| 118 | if (symbol_at((SID)i2) == sym) { |
| 119 | tty->print("*** Duplicate VM symbol SIDs %s(%d) and %s(%d): \"" , |
| 120 | vm_symbol_enum_name((SID)i2), i2, |
| 121 | vm_symbol_enum_name((SID)i1), i1); |
| 122 | sym->print_symbol_on(tty); |
| 123 | tty->print_cr("\"" ); |
| 124 | } |
| 125 | } |
| 126 | } |
| 127 | #endif //ASSERT |
| 128 | |
| 129 | // Create an index for find_id: |
| 130 | { |
| 131 | for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { |
| 132 | vm_symbol_index[index] = (SID)index; |
| 133 | } |
| 134 | int num_sids = SID_LIMIT-FIRST_SID; |
| 135 | qsort(&vm_symbol_index[FIRST_SID], num_sids, sizeof(vm_symbol_index[0]), |
| 136 | compare_vmsymbol_sid); |
| 137 | } |
| 138 | |
| 139 | #ifdef ASSERT |
| 140 | { |
| 141 | // Spot-check correspondence between strings, symbols, and enums: |
| 142 | assert(_symbols[NO_SID] == NULL, "must be" ); |
| 143 | const char* str = "java/lang/Object" ; |
| 144 | TempNewSymbol jlo = SymbolTable::new_permanent_symbol(str); |
| 145 | assert(strncmp(str, (char*)jlo->base(), jlo->utf8_length()) == 0, "" ); |
| 146 | assert(jlo == java_lang_Object(), "" ); |
| 147 | SID sid = VM_SYMBOL_ENUM_NAME(java_lang_Object); |
| 148 | assert(find_sid(jlo) == sid, "" ); |
| 149 | assert(symbol_at(sid) == jlo, "" ); |
| 150 | |
| 151 | // Make sure find_sid produces the right answer in each case. |
| 152 | for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { |
| 153 | Symbol* sym = symbol_at((SID)index); |
| 154 | sid = find_sid(sym); |
| 155 | assert(sid == (SID)index, "symbol index works" ); |
| 156 | // Note: If there are duplicates, this assert will fail. |
| 157 | // A "Duplicate VM symbol" message will have already been printed. |
| 158 | } |
| 159 | |
| 160 | // The string "format" happens (at the moment) not to be a vmSymbol, |
| 161 | // though it is a method name in java.lang.String. |
| 162 | str = "format" ; |
| 163 | TempNewSymbol fmt = SymbolTable::new_permanent_symbol(str); |
| 164 | sid = find_sid(fmt); |
| 165 | assert(sid == NO_SID, "symbol index works (negative test)" ); |
| 166 | } |
| 167 | #endif |
| 168 | } |
| 169 | |
| 170 | |
| 171 | #ifndef PRODUCT |
| 172 | const char* vmSymbols::name_for(vmSymbols::SID sid) { |
| 173 | if (sid == NO_SID) |
| 174 | return "NO_SID" ; |
| 175 | const char* string = &vm_symbol_bodies[0]; |
| 176 | for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { |
| 177 | if (index == (int)sid) |
| 178 | return string; |
| 179 | string += strlen(string); // skip string body |
| 180 | string += 1; // skip trailing null |
| 181 | } |
| 182 | return "BAD_SID" ; |
| 183 | } |
| 184 | #endif |
| 185 | |
| 186 | |
| 187 | |
| 188 | void vmSymbols::symbols_do(SymbolClosure* f) { |
| 189 | for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { |
| 190 | f->do_symbol(&_symbols[index]); |
| 191 | } |
| 192 | for (int i = 0; i < T_VOID+1; i++) { |
| 193 | f->do_symbol(&_type_signatures[i]); |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | void vmSymbols::metaspace_pointers_do(MetaspaceClosure *it) { |
| 198 | for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { |
| 199 | it->push(&_symbols[index]); |
| 200 | } |
| 201 | for (int i = 0; i < T_VOID+1; i++) { |
| 202 | it->push(&_type_signatures[i]); |
| 203 | } |
| 204 | } |
| 205 | |
| 206 | void vmSymbols::serialize(SerializeClosure* soc) { |
| 207 | soc->do_region((u_char*)&_symbols[FIRST_SID], |
| 208 | (SID_LIMIT - FIRST_SID) * sizeof(_symbols[0])); |
| 209 | soc->do_region((u_char*)_type_signatures, sizeof(_type_signatures)); |
| 210 | } |
| 211 | |
| 212 | |
| 213 | BasicType vmSymbols::signature_type(const Symbol* s) { |
| 214 | assert(s != NULL, "checking" ); |
| 215 | if (s->utf8_length() == 1) { |
| 216 | BasicType result = char2type(s->char_at(0)); |
| 217 | if (is_java_primitive(result) || result == T_VOID) { |
| 218 | assert(s == _type_signatures[result], "" ); |
| 219 | return result; |
| 220 | } |
| 221 | } |
| 222 | return T_OBJECT; |
| 223 | } |
| 224 | |
| 225 | |
| 226 | static int mid_hint = (int)vmSymbols::FIRST_SID+1; |
| 227 | |
| 228 | #ifndef PRODUCT |
| 229 | static int find_sid_calls, find_sid_probes; |
| 230 | // (Typical counts are calls=7000 and probes=17000.) |
| 231 | #endif |
| 232 | |
| 233 | vmSymbols::SID vmSymbols::find_sid(const Symbol* symbol) { |
| 234 | // Handle the majority of misses by a bounds check. |
| 235 | // Then, use a binary search over the index. |
| 236 | // Expected trip count is less than log2_SID_LIMIT, about eight. |
| 237 | // This is slow but acceptable, given that calls are not |
| 238 | // dynamically common. (Method*::intrinsic_id has a cache.) |
| 239 | NOT_PRODUCT(find_sid_calls++); |
| 240 | int min = (int)FIRST_SID, max = (int)SID_LIMIT - 1; |
| 241 | SID sid = NO_SID, sid1; |
| 242 | int cmp1; |
| 243 | sid1 = vm_symbol_index[min]; |
| 244 | cmp1 = compare_symbol(symbol, symbol_at(sid1)); |
| 245 | if (cmp1 <= 0) { // before the first |
| 246 | if (cmp1 == 0) sid = sid1; |
| 247 | } else { |
| 248 | sid1 = vm_symbol_index[max]; |
| 249 | cmp1 = compare_symbol(symbol, symbol_at(sid1)); |
| 250 | if (cmp1 >= 0) { // after the last |
| 251 | if (cmp1 == 0) sid = sid1; |
| 252 | } else { |
| 253 | // After checking the extremes, do a binary search. |
| 254 | ++min; --max; // endpoints are done |
| 255 | int mid = mid_hint; // start at previous success |
| 256 | while (max >= min) { |
| 257 | assert(mid >= min && mid <= max, "" ); |
| 258 | NOT_PRODUCT(find_sid_probes++); |
| 259 | sid1 = vm_symbol_index[mid]; |
| 260 | cmp1 = compare_symbol(symbol, symbol_at(sid1)); |
| 261 | if (cmp1 == 0) { |
| 262 | mid_hint = mid; |
| 263 | sid = sid1; |
| 264 | break; |
| 265 | } |
| 266 | if (cmp1 < 0) |
| 267 | max = mid - 1; // symbol < symbol_at(sid) |
| 268 | else |
| 269 | min = mid + 1; |
| 270 | |
| 271 | // Pick a new probe point: |
| 272 | mid = (max + min) / 2; |
| 273 | } |
| 274 | } |
| 275 | } |
| 276 | |
| 277 | #ifdef ASSERT |
| 278 | // Perform the exhaustive self-check the first 1000 calls, |
| 279 | // and every 100 calls thereafter. |
| 280 | static int find_sid_check_count = -2000; |
| 281 | if ((uint)++find_sid_check_count > (uint)100) { |
| 282 | if (find_sid_check_count > 0) find_sid_check_count = 0; |
| 283 | |
| 284 | // Make sure this is the right answer, using linear search. |
| 285 | // (We have already proven that there are no duplicates in the list.) |
| 286 | SID sid2 = NO_SID; |
| 287 | for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { |
| 288 | Symbol* sym2 = symbol_at((SID)index); |
| 289 | if (sym2 == symbol) { |
| 290 | sid2 = (SID)index; |
| 291 | break; |
| 292 | } |
| 293 | } |
| 294 | // Unless it's a duplicate, assert that the sids are the same. |
| 295 | if (_symbols[sid] != _symbols[sid2]) { |
| 296 | assert(sid == sid2, "binary same as linear search" ); |
| 297 | } |
| 298 | } |
| 299 | #endif //ASSERT |
| 300 | |
| 301 | return sid; |
| 302 | } |
| 303 | |
| 304 | vmSymbols::SID vmSymbols::find_sid(const char* symbol_name) { |
| 305 | Symbol* symbol = SymbolTable::probe(symbol_name, (int) strlen(symbol_name)); |
| 306 | if (symbol == NULL) return NO_SID; |
| 307 | return find_sid(symbol); |
| 308 | } |
| 309 | |
| 310 | static vmIntrinsics::ID wrapper_intrinsic(BasicType type, bool unboxing) { |
| 311 | #define TYPE2(type, unboxing) ((int)(type)*2 + ((unboxing) ? 1 : 0)) |
| 312 | switch (TYPE2(type, unboxing)) { |
| 313 | #define BASIC_TYPE_CASE(type, box, unbox) \ |
| 314 | case TYPE2(type, false): return vmIntrinsics::box; \ |
| 315 | case TYPE2(type, true): return vmIntrinsics::unbox |
| 316 | BASIC_TYPE_CASE(T_BOOLEAN, _Boolean_valueOf, _booleanValue); |
| 317 | BASIC_TYPE_CASE(T_BYTE, _Byte_valueOf, _byteValue); |
| 318 | BASIC_TYPE_CASE(T_CHAR, _Character_valueOf, _charValue); |
| 319 | BASIC_TYPE_CASE(T_SHORT, _Short_valueOf, _shortValue); |
| 320 | BASIC_TYPE_CASE(T_INT, _Integer_valueOf, _intValue); |
| 321 | BASIC_TYPE_CASE(T_LONG, _Long_valueOf, _longValue); |
| 322 | BASIC_TYPE_CASE(T_FLOAT, _Float_valueOf, _floatValue); |
| 323 | BASIC_TYPE_CASE(T_DOUBLE, _Double_valueOf, _doubleValue); |
| 324 | #undef BASIC_TYPE_CASE |
| 325 | } |
| 326 | #undef TYPE2 |
| 327 | return vmIntrinsics::_none; |
| 328 | } |
| 329 | |
| 330 | vmIntrinsics::ID vmIntrinsics::for_boxing(BasicType type) { |
| 331 | return wrapper_intrinsic(type, false); |
| 332 | } |
| 333 | vmIntrinsics::ID vmIntrinsics::for_unboxing(BasicType type) { |
| 334 | return wrapper_intrinsic(type, true); |
| 335 | } |
| 336 | |
| 337 | vmIntrinsics::ID vmIntrinsics::for_raw_conversion(BasicType src, BasicType dest) { |
| 338 | #define SRC_DEST(s,d) (((int)(s) << 4) + (int)(d)) |
| 339 | switch (SRC_DEST(src, dest)) { |
| 340 | case SRC_DEST(T_INT, T_FLOAT): return vmIntrinsics::_intBitsToFloat; |
| 341 | case SRC_DEST(T_FLOAT, T_INT): return vmIntrinsics::_floatToRawIntBits; |
| 342 | |
| 343 | case SRC_DEST(T_LONG, T_DOUBLE): return vmIntrinsics::_longBitsToDouble; |
| 344 | case SRC_DEST(T_DOUBLE, T_LONG): return vmIntrinsics::_doubleToRawLongBits; |
| 345 | } |
| 346 | #undef SRC_DEST |
| 347 | |
| 348 | return vmIntrinsics::_none; |
| 349 | } |
| 350 | |
| 351 | bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) { |
| 352 | assert(id != vmIntrinsics::_none, "must be a VM intrinsic" ); |
| 353 | switch(id) { |
| 354 | #ifdef JFR_HAVE_INTRINSICS |
| 355 | case vmIntrinsics::_counterTime: |
| 356 | #endif |
| 357 | case vmIntrinsics::_currentTimeMillis: |
| 358 | case vmIntrinsics::_nanoTime: |
| 359 | case vmIntrinsics::_floatToRawIntBits: |
| 360 | case vmIntrinsics::_intBitsToFloat: |
| 361 | case vmIntrinsics::_doubleToRawLongBits: |
| 362 | case vmIntrinsics::_longBitsToDouble: |
| 363 | case vmIntrinsics::_getClass: |
| 364 | case vmIntrinsics::_isInstance: |
| 365 | case vmIntrinsics::_currentThread: |
| 366 | case vmIntrinsics::_dabs: |
| 367 | case vmIntrinsics::_fabs: |
| 368 | case vmIntrinsics::_iabs: |
| 369 | case vmIntrinsics::_labs: |
| 370 | case vmIntrinsics::_dsqrt: |
| 371 | case vmIntrinsics::_dsin: |
| 372 | case vmIntrinsics::_dcos: |
| 373 | case vmIntrinsics::_dtan: |
| 374 | case vmIntrinsics::_dlog: |
| 375 | case vmIntrinsics::_dlog10: |
| 376 | case vmIntrinsics::_dexp: |
| 377 | case vmIntrinsics::_dpow: |
| 378 | case vmIntrinsics::_checkIndex: |
| 379 | case vmIntrinsics::_Reference_get: |
| 380 | case vmIntrinsics::_updateCRC32: |
| 381 | case vmIntrinsics::_updateBytesCRC32: |
| 382 | case vmIntrinsics::_updateByteBufferCRC32: |
| 383 | case vmIntrinsics::_vectorizedMismatch: |
| 384 | case vmIntrinsics::_fmaD: |
| 385 | case vmIntrinsics::_fmaF: |
| 386 | case vmIntrinsics::_isDigit: |
| 387 | case vmIntrinsics::_isLowerCase: |
| 388 | case vmIntrinsics::_isUpperCase: |
| 389 | case vmIntrinsics::_isWhitespace: |
| 390 | return true; |
| 391 | default: |
| 392 | return false; |
| 393 | } |
| 394 | } |
| 395 | |
| 396 | bool vmIntrinsics::can_trap(vmIntrinsics::ID id) { |
| 397 | assert(id != vmIntrinsics::_none, "must be a VM intrinsic" ); |
| 398 | switch(id) { |
| 399 | #ifdef JFR_HAVE_INTRINSICS |
| 400 | case vmIntrinsics::_counterTime: |
| 401 | case vmIntrinsics::_getClassId: |
| 402 | #endif |
| 403 | case vmIntrinsics::_currentTimeMillis: |
| 404 | case vmIntrinsics::_nanoTime: |
| 405 | case vmIntrinsics::_floatToRawIntBits: |
| 406 | case vmIntrinsics::_intBitsToFloat: |
| 407 | case vmIntrinsics::_doubleToRawLongBits: |
| 408 | case vmIntrinsics::_longBitsToDouble: |
| 409 | case vmIntrinsics::_currentThread: |
| 410 | case vmIntrinsics::_dabs: |
| 411 | case vmIntrinsics::_fabs: |
| 412 | case vmIntrinsics::_iabs: |
| 413 | case vmIntrinsics::_labs: |
| 414 | case vmIntrinsics::_dsqrt: |
| 415 | case vmIntrinsics::_dsin: |
| 416 | case vmIntrinsics::_dcos: |
| 417 | case vmIntrinsics::_dtan: |
| 418 | case vmIntrinsics::_dlog: |
| 419 | case vmIntrinsics::_dlog10: |
| 420 | case vmIntrinsics::_dexp: |
| 421 | case vmIntrinsics::_dpow: |
| 422 | case vmIntrinsics::_updateCRC32: |
| 423 | case vmIntrinsics::_updateBytesCRC32: |
| 424 | case vmIntrinsics::_updateByteBufferCRC32: |
| 425 | case vmIntrinsics::_vectorizedMismatch: |
| 426 | case vmIntrinsics::_fmaD: |
| 427 | case vmIntrinsics::_fmaF: |
| 428 | return false; |
| 429 | default: |
| 430 | return true; |
| 431 | } |
| 432 | } |
| 433 | |
| 434 | // Some intrinsics produce different results if they are not pinned |
| 435 | bool vmIntrinsics::should_be_pinned(vmIntrinsics::ID id) { |
| 436 | assert(id != vmIntrinsics::_none, "must be a VM intrinsic" ); |
| 437 | switch(id) { |
| 438 | #ifdef JFR_HAVE_INTRINSICS |
| 439 | case vmIntrinsics::_counterTime: |
| 440 | #endif |
| 441 | case vmIntrinsics::_currentTimeMillis: |
| 442 | case vmIntrinsics::_nanoTime: |
| 443 | return true; |
| 444 | default: |
| 445 | return false; |
| 446 | } |
| 447 | } |
| 448 | |
| 449 | bool vmIntrinsics::does_virtual_dispatch(vmIntrinsics::ID id) { |
| 450 | assert(id != vmIntrinsics::_none, "must be a VM intrinsic" ); |
| 451 | switch(id) { |
| 452 | case vmIntrinsics::_hashCode: |
| 453 | case vmIntrinsics::_clone: |
| 454 | return true; |
| 455 | break; |
| 456 | default: |
| 457 | return false; |
| 458 | } |
| 459 | } |
| 460 | |
| 461 | int vmIntrinsics::predicates_needed(vmIntrinsics::ID id) { |
| 462 | assert(id != vmIntrinsics::_none, "must be a VM intrinsic" ); |
| 463 | switch (id) { |
| 464 | case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: |
| 465 | case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: |
| 466 | case vmIntrinsics::_counterMode_AESCrypt: |
| 467 | return 1; |
| 468 | case vmIntrinsics::_digestBase_implCompressMB: |
| 469 | return 3; |
| 470 | default: |
| 471 | return 0; |
| 472 | } |
| 473 | } |
| 474 | |
| 475 | bool vmIntrinsics::is_intrinsic_available(vmIntrinsics::ID id) { |
| 476 | return !vmIntrinsics::is_intrinsic_disabled(id) && |
| 477 | !vmIntrinsics::is_disabled_by_flags(id); |
| 478 | } |
| 479 | |
| 480 | bool vmIntrinsics::is_intrinsic_disabled(vmIntrinsics::ID id) { |
| 481 | assert(id != vmIntrinsics::_none, "must be a VM intrinsic" ); |
| 482 | |
| 483 | // Canonicalize DisableIntrinsic to contain only ',' as a separator. |
| 484 | // Note, DirectiveSet may not be created at this point yet since this code |
| 485 | // is called from initial stub geenration code. |
| 486 | char* local_list = (char*)DirectiveSet::canonicalize_disableintrinsic(DisableIntrinsic); |
| 487 | char* save_ptr; |
| 488 | bool found = false; |
| 489 | |
| 490 | char* token = strtok_r(local_list, "," , &save_ptr); |
| 491 | while (token != NULL) { |
| 492 | if (strcmp(token, vmIntrinsics::name_at(id)) == 0) { |
| 493 | found = true; |
| 494 | break; |
| 495 | } else { |
| 496 | token = strtok_r(NULL, "," , &save_ptr); |
| 497 | } |
| 498 | } |
| 499 | |
| 500 | FREE_C_HEAP_ARRAY(char, local_list); |
| 501 | return found; |
| 502 | } |
| 503 | |
| 504 | |
| 505 | bool vmIntrinsics::is_disabled_by_flags(const methodHandle& method) { |
| 506 | vmIntrinsics::ID id = method->intrinsic_id(); |
| 507 | assert(id != vmIntrinsics::_none, "must be a VM intrinsic" ); |
| 508 | return is_disabled_by_flags(id); |
| 509 | } |
| 510 | |
| 511 | bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) { |
| 512 | assert(id != vmIntrinsics::_none, "must be a VM intrinsic" ); |
| 513 | |
| 514 | // -XX:-InlineNatives disables nearly all intrinsics except the ones listed in |
| 515 | // the following switch statement. |
| 516 | if (!InlineNatives) { |
| 517 | switch (id) { |
| 518 | case vmIntrinsics::_indexOfL: |
| 519 | case vmIntrinsics::_indexOfU: |
| 520 | case vmIntrinsics::_indexOfUL: |
| 521 | case vmIntrinsics::_indexOfIL: |
| 522 | case vmIntrinsics::_indexOfIU: |
| 523 | case vmIntrinsics::_indexOfIUL: |
| 524 | case vmIntrinsics::_indexOfU_char: |
| 525 | case vmIntrinsics::_compareToL: |
| 526 | case vmIntrinsics::_compareToU: |
| 527 | case vmIntrinsics::_compareToLU: |
| 528 | case vmIntrinsics::_compareToUL: |
| 529 | case vmIntrinsics::_equalsL: |
| 530 | case vmIntrinsics::_equalsU: |
| 531 | case vmIntrinsics::_equalsC: |
| 532 | case vmIntrinsics::_getCharStringU: |
| 533 | case vmIntrinsics::_putCharStringU: |
| 534 | case vmIntrinsics::_compressStringC: |
| 535 | case vmIntrinsics::_compressStringB: |
| 536 | case vmIntrinsics::_inflateStringC: |
| 537 | case vmIntrinsics::_inflateStringB: |
| 538 | case vmIntrinsics::_getAndAddInt: |
| 539 | case vmIntrinsics::_getAndAddLong: |
| 540 | case vmIntrinsics::_getAndSetInt: |
| 541 | case vmIntrinsics::_getAndSetLong: |
| 542 | case vmIntrinsics::_getAndSetReference: |
| 543 | case vmIntrinsics::_loadFence: |
| 544 | case vmIntrinsics::_storeFence: |
| 545 | case vmIntrinsics::_fullFence: |
| 546 | case vmIntrinsics::_hasNegatives: |
| 547 | case vmIntrinsics::_Reference_get: |
| 548 | break; |
| 549 | default: |
| 550 | return true; |
| 551 | } |
| 552 | } |
| 553 | |
| 554 | switch (id) { |
| 555 | case vmIntrinsics::_isInstance: |
| 556 | case vmIntrinsics::_isAssignableFrom: |
| 557 | case vmIntrinsics::_getModifiers: |
| 558 | case vmIntrinsics::_isInterface: |
| 559 | case vmIntrinsics::_isArray: |
| 560 | case vmIntrinsics::_isPrimitive: |
| 561 | case vmIntrinsics::_getSuperclass: |
| 562 | case vmIntrinsics::_Class_cast: |
| 563 | case vmIntrinsics::_getLength: |
| 564 | case vmIntrinsics::_newArray: |
| 565 | case vmIntrinsics::_getClass: |
| 566 | if (!InlineClassNatives) return true; |
| 567 | break; |
| 568 | case vmIntrinsics::_currentThread: |
| 569 | case vmIntrinsics::_isInterrupted: |
| 570 | if (!InlineThreadNatives) return true; |
| 571 | break; |
| 572 | case vmIntrinsics::_floatToRawIntBits: |
| 573 | case vmIntrinsics::_intBitsToFloat: |
| 574 | case vmIntrinsics::_doubleToRawLongBits: |
| 575 | case vmIntrinsics::_longBitsToDouble: |
| 576 | case vmIntrinsics::_dabs: |
| 577 | case vmIntrinsics::_fabs: |
| 578 | case vmIntrinsics::_iabs: |
| 579 | case vmIntrinsics::_labs: |
| 580 | case vmIntrinsics::_dsqrt: |
| 581 | case vmIntrinsics::_dsin: |
| 582 | case vmIntrinsics::_dcos: |
| 583 | case vmIntrinsics::_dtan: |
| 584 | case vmIntrinsics::_dlog: |
| 585 | case vmIntrinsics::_dexp: |
| 586 | case vmIntrinsics::_dpow: |
| 587 | case vmIntrinsics::_dlog10: |
| 588 | case vmIntrinsics::_datan2: |
| 589 | case vmIntrinsics::_min: |
| 590 | case vmIntrinsics::_max: |
| 591 | case vmIntrinsics::_floatToIntBits: |
| 592 | case vmIntrinsics::_doubleToLongBits: |
| 593 | case vmIntrinsics::_maxF: |
| 594 | case vmIntrinsics::_minF: |
| 595 | case vmIntrinsics::_maxD: |
| 596 | case vmIntrinsics::_minD: |
| 597 | if (!InlineMathNatives) return true; |
| 598 | break; |
| 599 | case vmIntrinsics::_fmaD: |
| 600 | case vmIntrinsics::_fmaF: |
| 601 | if (!InlineMathNatives || !UseFMA) return true; |
| 602 | break; |
| 603 | case vmIntrinsics::_arraycopy: |
| 604 | if (!InlineArrayCopy) return true; |
| 605 | break; |
| 606 | case vmIntrinsics::_updateCRC32: |
| 607 | case vmIntrinsics::_updateBytesCRC32: |
| 608 | case vmIntrinsics::_updateByteBufferCRC32: |
| 609 | if (!UseCRC32Intrinsics) return true; |
| 610 | break; |
| 611 | case vmIntrinsics::_getReference: |
| 612 | case vmIntrinsics::_getBoolean: |
| 613 | case vmIntrinsics::_getByte: |
| 614 | case vmIntrinsics::_getShort: |
| 615 | case vmIntrinsics::_getChar: |
| 616 | case vmIntrinsics::_getInt: |
| 617 | case vmIntrinsics::_getLong: |
| 618 | case vmIntrinsics::_getFloat: |
| 619 | case vmIntrinsics::_getDouble: |
| 620 | case vmIntrinsics::_putReference: |
| 621 | case vmIntrinsics::_putBoolean: |
| 622 | case vmIntrinsics::_putByte: |
| 623 | case vmIntrinsics::_putShort: |
| 624 | case vmIntrinsics::_putChar: |
| 625 | case vmIntrinsics::_putInt: |
| 626 | case vmIntrinsics::_putLong: |
| 627 | case vmIntrinsics::_putFloat: |
| 628 | case vmIntrinsics::_putDouble: |
| 629 | case vmIntrinsics::_getReferenceVolatile: |
| 630 | case vmIntrinsics::_getBooleanVolatile: |
| 631 | case vmIntrinsics::_getByteVolatile: |
| 632 | case vmIntrinsics::_getShortVolatile: |
| 633 | case vmIntrinsics::_getCharVolatile: |
| 634 | case vmIntrinsics::_getIntVolatile: |
| 635 | case vmIntrinsics::_getLongVolatile: |
| 636 | case vmIntrinsics::_getFloatVolatile: |
| 637 | case vmIntrinsics::_getDoubleVolatile: |
| 638 | case vmIntrinsics::_putReferenceVolatile: |
| 639 | case vmIntrinsics::_putBooleanVolatile: |
| 640 | case vmIntrinsics::_putByteVolatile: |
| 641 | case vmIntrinsics::_putShortVolatile: |
| 642 | case vmIntrinsics::_putCharVolatile: |
| 643 | case vmIntrinsics::_putIntVolatile: |
| 644 | case vmIntrinsics::_putLongVolatile: |
| 645 | case vmIntrinsics::_putFloatVolatile: |
| 646 | case vmIntrinsics::_putDoubleVolatile: |
| 647 | case vmIntrinsics::_getReferenceAcquire: |
| 648 | case vmIntrinsics::_getBooleanAcquire: |
| 649 | case vmIntrinsics::_getByteAcquire: |
| 650 | case vmIntrinsics::_getShortAcquire: |
| 651 | case vmIntrinsics::_getCharAcquire: |
| 652 | case vmIntrinsics::_getIntAcquire: |
| 653 | case vmIntrinsics::_getLongAcquire: |
| 654 | case vmIntrinsics::_getFloatAcquire: |
| 655 | case vmIntrinsics::_getDoubleAcquire: |
| 656 | case vmIntrinsics::_putReferenceRelease: |
| 657 | case vmIntrinsics::_putBooleanRelease: |
| 658 | case vmIntrinsics::_putByteRelease: |
| 659 | case vmIntrinsics::_putShortRelease: |
| 660 | case vmIntrinsics::_putCharRelease: |
| 661 | case vmIntrinsics::_putIntRelease: |
| 662 | case vmIntrinsics::_putLongRelease: |
| 663 | case vmIntrinsics::_putFloatRelease: |
| 664 | case vmIntrinsics::_putDoubleRelease: |
| 665 | case vmIntrinsics::_getReferenceOpaque: |
| 666 | case vmIntrinsics::_getBooleanOpaque: |
| 667 | case vmIntrinsics::_getByteOpaque: |
| 668 | case vmIntrinsics::_getShortOpaque: |
| 669 | case vmIntrinsics::_getCharOpaque: |
| 670 | case vmIntrinsics::_getIntOpaque: |
| 671 | case vmIntrinsics::_getLongOpaque: |
| 672 | case vmIntrinsics::_getFloatOpaque: |
| 673 | case vmIntrinsics::_getDoubleOpaque: |
| 674 | case vmIntrinsics::_putReferenceOpaque: |
| 675 | case vmIntrinsics::_putBooleanOpaque: |
| 676 | case vmIntrinsics::_putByteOpaque: |
| 677 | case vmIntrinsics::_putShortOpaque: |
| 678 | case vmIntrinsics::_putCharOpaque: |
| 679 | case vmIntrinsics::_putIntOpaque: |
| 680 | case vmIntrinsics::_putLongOpaque: |
| 681 | case vmIntrinsics::_putFloatOpaque: |
| 682 | case vmIntrinsics::_putDoubleOpaque: |
| 683 | case vmIntrinsics::_getAndAddInt: |
| 684 | case vmIntrinsics::_getAndAddLong: |
| 685 | case vmIntrinsics::_getAndSetInt: |
| 686 | case vmIntrinsics::_getAndSetLong: |
| 687 | case vmIntrinsics::_getAndSetReference: |
| 688 | case vmIntrinsics::_loadFence: |
| 689 | case vmIntrinsics::_storeFence: |
| 690 | case vmIntrinsics::_fullFence: |
| 691 | case vmIntrinsics::_compareAndSetLong: |
| 692 | case vmIntrinsics::_weakCompareAndSetLong: |
| 693 | case vmIntrinsics::_weakCompareAndSetLongPlain: |
| 694 | case vmIntrinsics::_weakCompareAndSetLongAcquire: |
| 695 | case vmIntrinsics::_weakCompareAndSetLongRelease: |
| 696 | case vmIntrinsics::_compareAndSetInt: |
| 697 | case vmIntrinsics::_weakCompareAndSetInt: |
| 698 | case vmIntrinsics::_weakCompareAndSetIntPlain: |
| 699 | case vmIntrinsics::_weakCompareAndSetIntAcquire: |
| 700 | case vmIntrinsics::_weakCompareAndSetIntRelease: |
| 701 | case vmIntrinsics::_compareAndSetReference: |
| 702 | case vmIntrinsics::_weakCompareAndSetReference: |
| 703 | case vmIntrinsics::_weakCompareAndSetReferencePlain: |
| 704 | case vmIntrinsics::_weakCompareAndSetReferenceAcquire: |
| 705 | case vmIntrinsics::_weakCompareAndSetReferenceRelease: |
| 706 | case vmIntrinsics::_compareAndExchangeInt: |
| 707 | case vmIntrinsics::_compareAndExchangeIntAcquire: |
| 708 | case vmIntrinsics::_compareAndExchangeIntRelease: |
| 709 | case vmIntrinsics::_compareAndExchangeLong: |
| 710 | case vmIntrinsics::_compareAndExchangeLongAcquire: |
| 711 | case vmIntrinsics::_compareAndExchangeLongRelease: |
| 712 | case vmIntrinsics::_compareAndExchangeReference: |
| 713 | case vmIntrinsics::_compareAndExchangeReferenceAcquire: |
| 714 | case vmIntrinsics::_compareAndExchangeReferenceRelease: |
| 715 | if (!InlineUnsafeOps) return true; |
| 716 | break; |
| 717 | case vmIntrinsics::_getShortUnaligned: |
| 718 | case vmIntrinsics::_getCharUnaligned: |
| 719 | case vmIntrinsics::_getIntUnaligned: |
| 720 | case vmIntrinsics::_getLongUnaligned: |
| 721 | case vmIntrinsics::_putShortUnaligned: |
| 722 | case vmIntrinsics::_putCharUnaligned: |
| 723 | case vmIntrinsics::_putIntUnaligned: |
| 724 | case vmIntrinsics::_putLongUnaligned: |
| 725 | case vmIntrinsics::_allocateInstance: |
| 726 | if (!InlineUnsafeOps || !UseUnalignedAccesses) return true; |
| 727 | break; |
| 728 | case vmIntrinsics::_hashCode: |
| 729 | if (!InlineObjectHash) return true; |
| 730 | break; |
| 731 | case vmIntrinsics::_aescrypt_encryptBlock: |
| 732 | case vmIntrinsics::_aescrypt_decryptBlock: |
| 733 | if (!UseAESIntrinsics) return true; |
| 734 | break; |
| 735 | case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: |
| 736 | case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: |
| 737 | if (!UseAESIntrinsics) return true; |
| 738 | break; |
| 739 | case vmIntrinsics::_counterMode_AESCrypt: |
| 740 | if (!UseAESCTRIntrinsics) return true; |
| 741 | break; |
| 742 | case vmIntrinsics::_sha_implCompress: |
| 743 | if (!UseSHA1Intrinsics) return true; |
| 744 | break; |
| 745 | case vmIntrinsics::_sha2_implCompress: |
| 746 | if (!UseSHA256Intrinsics) return true; |
| 747 | break; |
| 748 | case vmIntrinsics::_sha5_implCompress: |
| 749 | if (!UseSHA512Intrinsics) return true; |
| 750 | break; |
| 751 | case vmIntrinsics::_digestBase_implCompressMB: |
| 752 | if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) return true; |
| 753 | break; |
| 754 | case vmIntrinsics::_ghash_processBlocks: |
| 755 | if (!UseGHASHIntrinsics) return true; |
| 756 | break; |
| 757 | case vmIntrinsics::_base64_encodeBlock: |
| 758 | if (!UseBASE64Intrinsics) return true; |
| 759 | break; |
| 760 | case vmIntrinsics::_updateBytesCRC32C: |
| 761 | case vmIntrinsics::_updateDirectByteBufferCRC32C: |
| 762 | if (!UseCRC32CIntrinsics) return true; |
| 763 | break; |
| 764 | case vmIntrinsics::_vectorizedMismatch: |
| 765 | if (!UseVectorizedMismatchIntrinsic) return true; |
| 766 | break; |
| 767 | case vmIntrinsics::_updateBytesAdler32: |
| 768 | case vmIntrinsics::_updateByteBufferAdler32: |
| 769 | if (!UseAdler32Intrinsics) return true; |
| 770 | break; |
| 771 | case vmIntrinsics::_copyMemory: |
| 772 | if (!InlineArrayCopy || !InlineUnsafeOps) return true; |
| 773 | break; |
| 774 | #ifdef COMPILER1 |
| 775 | case vmIntrinsics::_checkIndex: |
| 776 | if (!InlineNIOCheckIndex) return true; |
| 777 | break; |
| 778 | #endif // COMPILER1 |
| 779 | #ifdef COMPILER2 |
| 780 | case vmIntrinsics::_clone: |
| 781 | #if INCLUDE_ZGC |
| 782 | if (UseZGC) return true; |
| 783 | #endif |
| 784 | case vmIntrinsics::_copyOf: |
| 785 | case vmIntrinsics::_copyOfRange: |
| 786 | // These intrinsics use both the objectcopy and the arraycopy |
| 787 | // intrinsic mechanism. |
| 788 | if (!InlineObjectCopy || !InlineArrayCopy) return true; |
| 789 | break; |
| 790 | case vmIntrinsics::_compareToL: |
| 791 | case vmIntrinsics::_compareToU: |
| 792 | case vmIntrinsics::_compareToLU: |
| 793 | case vmIntrinsics::_compareToUL: |
| 794 | if (!SpecialStringCompareTo) return true; |
| 795 | break; |
| 796 | case vmIntrinsics::_indexOfL: |
| 797 | case vmIntrinsics::_indexOfU: |
| 798 | case vmIntrinsics::_indexOfUL: |
| 799 | case vmIntrinsics::_indexOfIL: |
| 800 | case vmIntrinsics::_indexOfIU: |
| 801 | case vmIntrinsics::_indexOfIUL: |
| 802 | case vmIntrinsics::_indexOfU_char: |
| 803 | if (!SpecialStringIndexOf) return true; |
| 804 | break; |
| 805 | case vmIntrinsics::_equalsL: |
| 806 | case vmIntrinsics::_equalsU: |
| 807 | if (!SpecialStringEquals) return true; |
| 808 | break; |
| 809 | case vmIntrinsics::_equalsB: |
| 810 | case vmIntrinsics::_equalsC: |
| 811 | if (!SpecialArraysEquals) return true; |
| 812 | break; |
| 813 | case vmIntrinsics::_encodeISOArray: |
| 814 | case vmIntrinsics::_encodeByteISOArray: |
| 815 | if (!SpecialEncodeISOArray) return true; |
| 816 | break; |
| 817 | case vmIntrinsics::_getCallerClass: |
| 818 | if (!InlineReflectionGetCallerClass) return true; |
| 819 | break; |
| 820 | case vmIntrinsics::_multiplyToLen: |
| 821 | if (!UseMultiplyToLenIntrinsic) return true; |
| 822 | break; |
| 823 | case vmIntrinsics::_squareToLen: |
| 824 | if (!UseSquareToLenIntrinsic) return true; |
| 825 | break; |
| 826 | case vmIntrinsics::_mulAdd: |
| 827 | if (!UseMulAddIntrinsic) return true; |
| 828 | break; |
| 829 | case vmIntrinsics::_montgomeryMultiply: |
| 830 | if (!UseMontgomeryMultiplyIntrinsic) return true; |
| 831 | break; |
| 832 | case vmIntrinsics::_montgomerySquare: |
| 833 | if (!UseMontgomerySquareIntrinsic) return true; |
| 834 | break; |
| 835 | case vmIntrinsics::_addExactI: |
| 836 | case vmIntrinsics::_addExactL: |
| 837 | case vmIntrinsics::_decrementExactI: |
| 838 | case vmIntrinsics::_decrementExactL: |
| 839 | case vmIntrinsics::_incrementExactI: |
| 840 | case vmIntrinsics::_incrementExactL: |
| 841 | case vmIntrinsics::_multiplyExactI: |
| 842 | case vmIntrinsics::_multiplyExactL: |
| 843 | case vmIntrinsics::_negateExactI: |
| 844 | case vmIntrinsics::_negateExactL: |
| 845 | case vmIntrinsics::_subtractExactI: |
| 846 | case vmIntrinsics::_subtractExactL: |
| 847 | if (!UseMathExactIntrinsics || !InlineMathNatives) return true; |
| 848 | break; |
| 849 | case vmIntrinsics::_isDigit: |
| 850 | case vmIntrinsics::_isLowerCase: |
| 851 | case vmIntrinsics::_isUpperCase: |
| 852 | case vmIntrinsics::_isWhitespace: |
| 853 | if (!UseCharacterCompareIntrinsics) return true; |
| 854 | break; |
| 855 | #endif // COMPILER2 |
| 856 | default: |
| 857 | return false; |
| 858 | } |
| 859 | |
| 860 | return false; |
| 861 | } |
| 862 | |
| 863 | #define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0" |
| 864 | static const char* vm_intrinsic_name_bodies = |
| 865 | VM_INTRINSICS_DO(VM_INTRINSIC_INITIALIZE, |
| 866 | VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); |
| 867 | |
| 868 | static const char* vm_intrinsic_name_table[vmIntrinsics::ID_LIMIT]; |
| 869 | |
| 870 | const char* vmIntrinsics::name_at(vmIntrinsics::ID id) { |
| 871 | const char** nt = &vm_intrinsic_name_table[0]; |
| 872 | if (nt[_none] == NULL) { |
| 873 | char* string = (char*) &vm_intrinsic_name_bodies[0]; |
| 874 | for (int index = FIRST_ID; index < ID_LIMIT; index++) { |
| 875 | nt[index] = string; |
| 876 | string += strlen(string); // skip string body |
| 877 | string += 1; // skip trailing null |
| 878 | } |
| 879 | assert(!strcmp(nt[_hashCode], "_hashCode" ), "lined up" ); |
| 880 | nt[_none] = "_none" ; |
| 881 | } |
| 882 | if ((uint)id < (uint)ID_LIMIT) |
| 883 | return vm_intrinsic_name_table[(uint)id]; |
| 884 | else |
| 885 | return "(unknown intrinsic)" ; |
| 886 | } |
| 887 | |
| 888 | // These are flag-matching functions: |
| 889 | inline bool match_F_R(jshort flags) { |
| 890 | const int req = 0; |
| 891 | const int neg = JVM_ACC_STATIC | JVM_ACC_SYNCHRONIZED; |
| 892 | return (flags & (req | neg)) == req; |
| 893 | } |
| 894 | inline bool match_F_Y(jshort flags) { |
| 895 | const int req = JVM_ACC_SYNCHRONIZED; |
| 896 | const int neg = JVM_ACC_STATIC; |
| 897 | return (flags & (req | neg)) == req; |
| 898 | } |
| 899 | inline bool match_F_RN(jshort flags) { |
| 900 | const int req = JVM_ACC_NATIVE; |
| 901 | const int neg = JVM_ACC_STATIC | JVM_ACC_SYNCHRONIZED; |
| 902 | return (flags & (req | neg)) == req; |
| 903 | } |
| 904 | inline bool match_F_S(jshort flags) { |
| 905 | const int req = JVM_ACC_STATIC; |
| 906 | const int neg = JVM_ACC_SYNCHRONIZED; |
| 907 | return (flags & (req | neg)) == req; |
| 908 | } |
| 909 | inline bool match_F_SN(jshort flags) { |
| 910 | const int req = JVM_ACC_STATIC | JVM_ACC_NATIVE; |
| 911 | const int neg = JVM_ACC_SYNCHRONIZED; |
| 912 | return (flags & (req | neg)) == req; |
| 913 | } |
| 914 | inline bool match_F_RNY(jshort flags) { |
| 915 | const int req = JVM_ACC_NATIVE | JVM_ACC_SYNCHRONIZED; |
| 916 | const int neg = JVM_ACC_STATIC; |
| 917 | return (flags & (req | neg)) == req; |
| 918 | } |
| 919 | |
| 920 | // These are for forming case labels: |
| 921 | #define ID3(x, y, z) (( jlong)(z) + \ |
| 922 | ((jlong)(y) << vmSymbols::log2_SID_LIMIT) + \ |
| 923 | ((jlong)(x) << (2*vmSymbols::log2_SID_LIMIT)) ) |
| 924 | #define SID_ENUM(n) vmSymbols::VM_SYMBOL_ENUM_NAME(n) |
| 925 | |
| 926 | vmIntrinsics::ID vmIntrinsics::find_id_impl(vmSymbols::SID holder, |
| 927 | vmSymbols::SID name, |
| 928 | vmSymbols::SID sig, |
| 929 | jshort flags) { |
| 930 | assert((int)vmSymbols::SID_LIMIT <= (1<<vmSymbols::log2_SID_LIMIT), "must fit" ); |
| 931 | |
| 932 | // Let the C compiler build the decision tree. |
| 933 | |
| 934 | #define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \ |
| 935 | case ID3(SID_ENUM(klass), SID_ENUM(name), SID_ENUM(sig)): \ |
| 936 | if (!match_##fcode(flags)) break; \ |
| 937 | return id; |
| 938 | |
| 939 | switch (ID3(holder, name, sig)) { |
| 940 | VM_INTRINSICS_DO(VM_INTRINSIC_CASE, |
| 941 | VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); |
| 942 | } |
| 943 | return vmIntrinsics::_none; |
| 944 | |
| 945 | #undef VM_INTRINSIC_CASE |
| 946 | } |
| 947 | |
| 948 | |
| 949 | const char* vmIntrinsics::short_name_as_C_string(vmIntrinsics::ID id, char* buf, int buflen) { |
| 950 | const char* str = name_at(id); |
| 951 | #ifndef PRODUCT |
| 952 | const char* kname = vmSymbols::name_for(class_for(id)); |
| 953 | const char* mname = vmSymbols::name_for(name_for(id)); |
| 954 | const char* sname = vmSymbols::name_for(signature_for(id)); |
| 955 | const char* fname = "" ; |
| 956 | switch (flags_for(id)) { |
| 957 | case F_Y: fname = "synchronized " ; break; |
| 958 | case F_RN: fname = "native " ; break; |
| 959 | case F_SN: fname = "native static " ; break; |
| 960 | case F_S: fname = "static " ; break; |
| 961 | case F_RNY:fname = "native synchronized " ; break; |
| 962 | default: break; |
| 963 | } |
| 964 | const char* kptr = strrchr(kname, '/'); |
| 965 | if (kptr != NULL) kname = kptr + 1; |
| 966 | int len = jio_snprintf(buf, buflen, "%s: %s%s.%s%s" , |
| 967 | str, fname, kname, mname, sname); |
| 968 | if (len < buflen) |
| 969 | str = buf; |
| 970 | #endif //PRODUCT |
| 971 | return str; |
| 972 | } |
| 973 | |
| 974 | |
| 975 | // These are to get information about intrinsics. |
| 976 | |
| 977 | #define ID4(x, y, z, f) ((ID3(x, y, z) << vmIntrinsics::log2_FLAG_LIMIT) | (jlong) (f)) |
| 978 | |
| 979 | static const jlong intrinsic_info_array[vmIntrinsics::ID_LIMIT+1] = { |
| 980 | #define VM_INTRINSIC_INFO(ignore_id, klass, name, sig, fcode) \ |
| 981 | ID4(SID_ENUM(klass), SID_ENUM(name), SID_ENUM(sig), vmIntrinsics::fcode), |
| 982 | |
| 983 | 0, VM_INTRINSICS_DO(VM_INTRINSIC_INFO, |
| 984 | VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) |
| 985 | 0 |
| 986 | #undef VM_INTRINSIC_INFO |
| 987 | }; |
| 988 | |
| 989 | inline jlong intrinsic_info(vmIntrinsics::ID id) { |
| 990 | return intrinsic_info_array[vmIntrinsics::ID_from((int)id)]; |
| 991 | } |
| 992 | |
| 993 | vmSymbols::SID vmIntrinsics::class_for(vmIntrinsics::ID id) { |
| 994 | jlong info = intrinsic_info(id); |
| 995 | int shift = 2*vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT); |
| 996 | assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1021, "" ); |
| 997 | return vmSymbols::SID( (info >> shift) & mask ); |
| 998 | } |
| 999 | |
| 1000 | vmSymbols::SID vmIntrinsics::name_for(vmIntrinsics::ID id) { |
| 1001 | jlong info = intrinsic_info(id); |
| 1002 | int shift = vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT); |
| 1003 | assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1022, "" ); |
| 1004 | return vmSymbols::SID( (info >> shift) & mask ); |
| 1005 | } |
| 1006 | |
| 1007 | vmSymbols::SID vmIntrinsics::signature_for(vmIntrinsics::ID id) { |
| 1008 | jlong info = intrinsic_info(id); |
| 1009 | int shift = log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT); |
| 1010 | assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1023, "" ); |
| 1011 | return vmSymbols::SID( (info >> shift) & mask ); |
| 1012 | } |
| 1013 | |
| 1014 | vmIntrinsics::Flags vmIntrinsics::flags_for(vmIntrinsics::ID id) { |
| 1015 | jlong info = intrinsic_info(id); |
| 1016 | int shift = 0, mask = right_n_bits(log2_FLAG_LIMIT); |
| 1017 | assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 15, "" ); |
| 1018 | return Flags( (info >> shift) & mask ); |
| 1019 | } |
| 1020 | |
| 1021 | |
| 1022 | #ifndef PRODUCT |
| 1023 | // verify_method performs an extra check on a matched intrinsic method |
| 1024 | |
| 1025 | static bool match_method(Method* m, Symbol* n, Symbol* s) { |
| 1026 | return (m->name() == n && |
| 1027 | m->signature() == s); |
| 1028 | } |
| 1029 | |
| 1030 | static vmIntrinsics::ID match_method_with_klass(Method* m, Symbol* mk) { |
| 1031 | #define VM_INTRINSIC_MATCH(id, klassname, namepart, sigpart, flags) \ |
| 1032 | { Symbol* k = vmSymbols::klassname(); \ |
| 1033 | if (mk == k) { \ |
| 1034 | Symbol* n = vmSymbols::namepart(); \ |
| 1035 | Symbol* s = vmSymbols::sigpart(); \ |
| 1036 | if (match_method(m, n, s)) \ |
| 1037 | return vmIntrinsics::id; \ |
| 1038 | } } |
| 1039 | VM_INTRINSICS_DO(VM_INTRINSIC_MATCH, |
| 1040 | VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE); |
| 1041 | return vmIntrinsics::_none; |
| 1042 | #undef VM_INTRINSIC_MATCH |
| 1043 | } |
| 1044 | |
| 1045 | void vmIntrinsics::verify_method(ID actual_id, Method* m) { |
| 1046 | Symbol* mk = m->method_holder()->name(); |
| 1047 | ID declared_id = match_method_with_klass(m, mk); |
| 1048 | |
| 1049 | if (declared_id == actual_id) return; // success |
| 1050 | |
| 1051 | if (declared_id == _none && actual_id != _none && mk == vmSymbols::java_lang_StrictMath()) { |
| 1052 | // Here are a few special cases in StrictMath not declared in vmSymbols.hpp. |
| 1053 | switch (actual_id) { |
| 1054 | case _min: |
| 1055 | case _max: |
| 1056 | case _dsqrt: |
| 1057 | declared_id = match_method_with_klass(m, vmSymbols::java_lang_Math()); |
| 1058 | if (declared_id == actual_id) return; // acceptable alias |
| 1059 | break; |
| 1060 | default: |
| 1061 | break; |
| 1062 | } |
| 1063 | } |
| 1064 | |
| 1065 | const char* declared_name = name_at(declared_id); |
| 1066 | const char* actual_name = name_at(actual_id); |
| 1067 | methodHandle mh = m; |
| 1068 | m = NULL; |
| 1069 | ttyLocker ttyl; |
| 1070 | if (xtty != NULL) { |
| 1071 | xtty->begin_elem("intrinsic_misdeclared actual='%s' declared='%s'" , |
| 1072 | actual_name, declared_name); |
| 1073 | xtty->method(mh); |
| 1074 | xtty->end_elem("%s" , "" ); |
| 1075 | } |
| 1076 | if (PrintMiscellaneous && (WizardMode || Verbose)) { |
| 1077 | tty->print_cr("*** misidentified method; %s(%d) should be %s(%d):" , |
| 1078 | declared_name, declared_id, actual_name, actual_id); |
| 1079 | mh()->print_short_name(tty); |
| 1080 | tty->cr(); |
| 1081 | } |
| 1082 | } |
| 1083 | #endif //PRODUCT |
| 1084 | |