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 | |