| File: | jdk/src/hotspot/share/runtime/signature.hpp |
| Warning: | line 502, column 31 Undefined or garbage value returned to caller |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* | ||||
| 2 | * Copyright (c) 1997, 2021, 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 "classfile/symbolTable.hpp" | ||||
| 27 | #include "classfile/systemDictionary.hpp" | ||||
| 28 | #include "classfile/vmSymbols.hpp" | ||||
| 29 | #include "memory/oopFactory.hpp" | ||||
| 30 | #include "memory/resourceArea.hpp" | ||||
| 31 | #include "memory/universe.hpp" | ||||
| 32 | #include "oops/instanceKlass.hpp" | ||||
| 33 | #include "oops/klass.inline.hpp" | ||||
| 34 | #include "oops/oop.inline.hpp" | ||||
| 35 | #include "oops/symbol.hpp" | ||||
| 36 | #include "oops/typeArrayKlass.hpp" | ||||
| 37 | #include "runtime/fieldDescriptor.inline.hpp" | ||||
| 38 | #include "runtime/handles.inline.hpp" | ||||
| 39 | #include "runtime/safepointVerifiers.hpp" | ||||
| 40 | #include "runtime/signature.hpp" | ||||
| 41 | |||||
| 42 | // Implementation of SignatureIterator | ||||
| 43 | |||||
| 44 | // Signature syntax: | ||||
| 45 | // | ||||
| 46 | // Signature = "(" {Parameter} ")" ReturnType. | ||||
| 47 | // Parameter = FieldType. | ||||
| 48 | // ReturnType = FieldType | "V". | ||||
| 49 | // FieldType = "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z" | "L" ClassName ";" | "[" FieldType. | ||||
| 50 | // ClassName = string. | ||||
| 51 | |||||
| 52 | // The ClassName string can be any JVM-style UTF8 string except: | ||||
| 53 | // - an empty string (the empty string is never a name of any kind) | ||||
| 54 | // - a string which begins or ends with slash '/' (the package separator) | ||||
| 55 | // - a string which contains adjacent slashes '//' (no empty package names) | ||||
| 56 | // - a string which contains a semicolon ';' (the end-delimiter) | ||||
| 57 | // - a string which contains a left bracket '[' (the array marker) | ||||
| 58 | // - a string which contains a dot '.' (the external package separator) | ||||
| 59 | // | ||||
| 60 | // Other "meta-looking" characters, such as '(' and '<' and '+', | ||||
| 61 | // are perfectly legitimate within a class name, for the JVM. | ||||
| 62 | // Class names which contain double slashes ('a//b') and non-initial | ||||
| 63 | // brackets ('a[b]') are reserved for possible enrichment of the | ||||
| 64 | // type language. | ||||
| 65 | |||||
| 66 | void SignatureIterator::set_fingerprint(fingerprint_t fingerprint) { | ||||
| 67 | if (!fp_is_valid(fingerprint)) { | ||||
| 68 | _fingerprint = fingerprint; | ||||
| 69 | _return_type = T_ILLEGAL; | ||||
| 70 | } else if (fingerprint != _fingerprint) { | ||||
| 71 | assert(_fingerprint == zero_fingerprint(), "consistent fingerprint values")do { if (!(_fingerprint == zero_fingerprint())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 71, "assert(" "_fingerprint == zero_fingerprint()" ") failed" , "consistent fingerprint values"); ::breakpoint(); } } while (0); | ||||
| 72 | _fingerprint = fingerprint; | ||||
| 73 | _return_type = fp_return_type(fingerprint); | ||||
| 74 | } | ||||
| 75 | } | ||||
| 76 | |||||
| 77 | BasicType SignatureIterator::return_type() { | ||||
| 78 | if (_return_type == T_ILLEGAL) { | ||||
| 79 | SignatureStream ss(_signature); | ||||
| 80 | ss.skip_to_return_type(); | ||||
| 81 | _return_type = ss.type(); | ||||
| 82 | assert(_return_type != T_ILLEGAL, "illegal return type")do { if (!(_return_type != T_ILLEGAL)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 82, "assert(" "_return_type != T_ILLEGAL" ") failed", "illegal return type" ); ::breakpoint(); } } while (0); | ||||
| 83 | } | ||||
| 84 | return _return_type; | ||||
| 85 | } | ||||
| 86 | |||||
| 87 | bool SignatureIterator::fp_is_valid_type(BasicType type, bool for_return_type) { | ||||
| 88 | assert(type != (BasicType)fp_parameters_done, "fingerprint is incorrectly at done")do { if (!(type != (BasicType)fp_parameters_done)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 88, "assert(" "type != (BasicType)fp_parameters_done" ") failed" , "fingerprint is incorrectly at done"); ::breakpoint(); } } while (0); | ||||
| 89 | assert(((int)type & ~fp_parameter_feature_mask) == 0, "fingerprint feature mask yielded non-zero value")do { if (!(((int)type & ~fp_parameter_feature_mask) == 0) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 89, "assert(" "((int)type & ~fp_parameter_feature_mask) == 0" ") failed", "fingerprint feature mask yielded non-zero value" ); ::breakpoint(); } } while (0); | ||||
| 90 | return (is_java_primitive(type) || | ||||
| 91 | is_reference_type(type) || | ||||
| 92 | (for_return_type && type == T_VOID)); | ||||
| 93 | } | ||||
| 94 | |||||
| 95 | ArgumentSizeComputer::ArgumentSizeComputer(Symbol* signature) | ||||
| 96 | : SignatureIterator(signature) | ||||
| 97 | { | ||||
| 98 | _size = 0; | ||||
| 99 | do_parameters_on(this); // non-virtual template execution | ||||
| 100 | } | ||||
| 101 | |||||
| 102 | ArgumentCount::ArgumentCount(Symbol* signature) | ||||
| 103 | : SignatureIterator(signature) | ||||
| 104 | { | ||||
| 105 | _size = 0; | ||||
| 106 | do_parameters_on(this); // non-virtual template execution | ||||
| 107 | } | ||||
| 108 | |||||
| 109 | ReferenceArgumentCount::ReferenceArgumentCount(Symbol* signature) | ||||
| 110 | : SignatureIterator(signature) | ||||
| 111 | { | ||||
| 112 | _refs = 0; | ||||
| 113 | do_parameters_on(this); // non-virtual template execution | ||||
| |||||
| 114 | } | ||||
| 115 | |||||
| 116 | void Fingerprinter::compute_fingerprint_and_return_type(bool static_flag) { | ||||
| 117 | // See if we fingerprinted this method already | ||||
| 118 | if (_method != NULL__null) { | ||||
| 119 | assert(!static_flag, "must not be passed by caller")do { if (!(!static_flag)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 119, "assert(" "!static_flag" ") failed", "must not be passed by caller" ); ::breakpoint(); } } while (0); | ||||
| 120 | static_flag = _method->is_static(); | ||||
| 121 | _fingerprint = _method->constMethod()->fingerprint(); | ||||
| 122 | |||||
| 123 | if (_fingerprint != zero_fingerprint()) { | ||||
| 124 | _return_type = _method->result_type(); | ||||
| 125 | assert(is_java_type(_return_type), "return type must be a java type")do { if (!(is_java_type(_return_type))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 125, "assert(" "is_java_type(_return_type)" ") failed", "return type must be a java type" ); ::breakpoint(); } } while (0); | ||||
| 126 | return; | ||||
| 127 | } | ||||
| 128 | |||||
| 129 | if (_method->size_of_parameters() > fp_max_size_of_parameters) { | ||||
| 130 | _fingerprint = overflow_fingerprint(); | ||||
| 131 | _method->constMethod()->set_fingerprint(_fingerprint); | ||||
| 132 | // as long as we are here compute the return type: | ||||
| 133 | _return_type = ResultTypeFinder(_method->signature()).type(); | ||||
| 134 | assert(is_java_type(_return_type), "return type must be a java type")do { if (!(is_java_type(_return_type))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 134, "assert(" "is_java_type(_return_type)" ") failed", "return type must be a java type" ); ::breakpoint(); } } while (0); | ||||
| 135 | return; | ||||
| 136 | } | ||||
| 137 | } | ||||
| 138 | |||||
| 139 | // Note: This will always take the slow path, since _fp==zero_fp. | ||||
| 140 | initialize_accumulator(); | ||||
| 141 | do_parameters_on(this); | ||||
| 142 | assert(fp_is_valid_type(_return_type, true), "bad result type")do { if (!(fp_is_valid_type(_return_type, true))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 142, "assert(" "fp_is_valid_type(_return_type, true)" ") failed" , "bad result type"); ::breakpoint(); } } while (0); | ||||
| 143 | |||||
| 144 | // Fill in the return type and static bits: | ||||
| 145 | _accumulator |= _return_type << fp_static_feature_size; | ||||
| 146 | if (static_flag) { | ||||
| 147 | _accumulator |= fp_is_static_bit; | ||||
| 148 | } else { | ||||
| 149 | _param_size += 1; // this is the convention for Method::compute_size_of_parameters | ||||
| 150 | } | ||||
| 151 | |||||
| 152 | // Detect overflow. (We counted _param_size correctly.) | ||||
| 153 | if (_method == NULL__null && _param_size > fp_max_size_of_parameters) { | ||||
| 154 | // We did a one-pass computation of argument size, return type, | ||||
| 155 | // and fingerprint. | ||||
| 156 | _fingerprint = overflow_fingerprint(); | ||||
| 157 | return; | ||||
| 158 | } | ||||
| 159 | |||||
| 160 | assert(_shift_count < BitsPerLong,do { if (!(_shift_count < BitsPerLong)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 163, "assert(" "_shift_count < BitsPerLong" ") failed", "shift count overflow %d (%d vs. %d): %s" , _shift_count, _param_size, fp_max_size_of_parameters, _signature ->as_C_string()); ::breakpoint(); } } while (0) | ||||
| 161 | "shift count overflow %d (%d vs. %d): %s",do { if (!(_shift_count < BitsPerLong)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 163, "assert(" "_shift_count < BitsPerLong" ") failed", "shift count overflow %d (%d vs. %d): %s" , _shift_count, _param_size, fp_max_size_of_parameters, _signature ->as_C_string()); ::breakpoint(); } } while (0) | ||||
| 162 | _shift_count, _param_size, fp_max_size_of_parameters,do { if (!(_shift_count < BitsPerLong)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 163, "assert(" "_shift_count < BitsPerLong" ") failed", "shift count overflow %d (%d vs. %d): %s" , _shift_count, _param_size, fp_max_size_of_parameters, _signature ->as_C_string()); ::breakpoint(); } } while (0) | ||||
| 163 | _signature->as_C_string())do { if (!(_shift_count < BitsPerLong)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 163, "assert(" "_shift_count < BitsPerLong" ") failed", "shift count overflow %d (%d vs. %d): %s" , _shift_count, _param_size, fp_max_size_of_parameters, _signature ->as_C_string()); ::breakpoint(); } } while (0); | ||||
| 164 | assert((_accumulator >> _shift_count) == fp_parameters_done, "must be zero")do { if (!((_accumulator >> _shift_count) == fp_parameters_done )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 164, "assert(" "(_accumulator >> _shift_count) == fp_parameters_done" ") failed", "must be zero"); ::breakpoint(); } } while (0); | ||||
| 165 | |||||
| 166 | // This is the result, along with _return_type: | ||||
| 167 | _fingerprint = _accumulator; | ||||
| 168 | |||||
| 169 | // Cache the result on the method itself: | ||||
| 170 | if (_method != NULL__null) { | ||||
| 171 | _method->constMethod()->set_fingerprint(_fingerprint); | ||||
| 172 | } | ||||
| 173 | } | ||||
| 174 | |||||
| 175 | // Implementation of SignatureStream | ||||
| 176 | |||||
| 177 | static inline BasicType decode_signature_char(int ch) { | ||||
| 178 | switch (ch) { | ||||
| 179 | #define EACH_SIG(ch, bt, ignore) \ | ||||
| 180 | case ch: return bt; | ||||
| 181 | SIGNATURE_TYPES_DO(EACH_SIG, ignore)EACH_SIG(JVM_SIGNATURE_BOOLEAN, T_BOOLEAN, ignore) EACH_SIG(JVM_SIGNATURE_CHAR , T_CHAR, ignore) EACH_SIG(JVM_SIGNATURE_FLOAT, T_FLOAT, ignore ) EACH_SIG(JVM_SIGNATURE_DOUBLE, T_DOUBLE, ignore) EACH_SIG(JVM_SIGNATURE_BYTE , T_BYTE, ignore) EACH_SIG(JVM_SIGNATURE_SHORT, T_SHORT, ignore ) EACH_SIG(JVM_SIGNATURE_INT, T_INT, ignore) EACH_SIG(JVM_SIGNATURE_LONG , T_LONG, ignore) EACH_SIG(JVM_SIGNATURE_CLASS, T_OBJECT, ignore ) EACH_SIG(JVM_SIGNATURE_ARRAY, T_ARRAY, ignore) EACH_SIG(JVM_SIGNATURE_VOID , T_VOID, ignore) | ||||
| 182 | #undef EACH_SIG | ||||
| 183 | } | ||||
| 184 | return (BasicType)0; | ||||
| 185 | } | ||||
| 186 | |||||
| 187 | SignatureStream::SignatureStream(const Symbol* signature, | ||||
| 188 | bool is_method) { | ||||
| 189 | assert(!is_method || signature->starts_with(JVM_SIGNATURE_FUNC),do { if (!(!is_method || signature->starts_with(JVM_SIGNATURE_FUNC ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 190, "assert(" "!is_method || signature->starts_with(JVM_SIGNATURE_FUNC)" ") failed", "method signature required"); ::breakpoint(); } } while (0) | ||||
| 190 | "method signature required")do { if (!(!is_method || signature->starts_with(JVM_SIGNATURE_FUNC ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 190, "assert(" "!is_method || signature->starts_with(JVM_SIGNATURE_FUNC)" ") failed", "method signature required"); ::breakpoint(); } } while (0); | ||||
| 191 | _signature = signature; | ||||
| 192 | _limit = signature->utf8_length(); | ||||
| 193 | int oz = (is_method
| ||||
| 194 | _state = oz; | ||||
| 195 | _begin = _end = oz; // skip first '(' in method signatures | ||||
| 196 | _array_prefix = 0; // just for definiteness | ||||
| 197 | |||||
| 198 | // assigning java/lang/Object to _previous_name means we can | ||||
| 199 | // avoid a number of NULL checks in the parser | ||||
| 200 | _previous_name = vmSymbols::java_lang_Object(); | ||||
| 201 | _names = NULL__null; | ||||
| 202 | next(); | ||||
| 203 | } | ||||
| 204 | |||||
| 205 | SignatureStream::~SignatureStream() { | ||||
| 206 | if (_previous_name == vmSymbols::java_lang_Object()) { | ||||
| 207 | // no names were created | ||||
| 208 | assert(_names == NULL, "_names unexpectedly created")do { if (!(_names == __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 208, "assert(" "_names == __null" ") failed", "_names unexpectedly created" ); ::breakpoint(); } } while (0); | ||||
| 209 | return; | ||||
| 210 | } | ||||
| 211 | |||||
| 212 | // decrement refcount for names created during signature parsing | ||||
| 213 | _previous_name->decrement_refcount(); | ||||
| 214 | if (_names != NULL__null) { | ||||
| 215 | for (int i = 0; i < _names->length(); i++) { | ||||
| 216 | _names->at(i)->decrement_refcount(); | ||||
| 217 | } | ||||
| 218 | } | ||||
| 219 | } | ||||
| 220 | |||||
| 221 | inline int SignatureStream::scan_type(BasicType type) { | ||||
| 222 | const u1* base = _signature->bytes(); | ||||
| 223 | int end = _end; | ||||
| 224 | int limit = _limit; | ||||
| 225 | const u1* tem; | ||||
| 226 | switch (type) { | ||||
| 227 | case T_OBJECT: | ||||
| 228 | tem = (const u1*) memchr(&base[end], JVM_SIGNATURE_ENDCLASS, limit - end); | ||||
| 229 | return (tem == NULL__null ? limit : tem + 1 - base); | ||||
| 230 | |||||
| 231 | case T_ARRAY: | ||||
| 232 | while ((end < limit) && ((char)base[end] == JVM_SIGNATURE_ARRAY)) { end++; } | ||||
| 233 | _array_prefix = end - _end; // number of '[' chars just skipped | ||||
| 234 | if (Signature::has_envelope(base[end])) { | ||||
| 235 | tem = (const u1 *) memchr(&base[end], JVM_SIGNATURE_ENDCLASS, limit - end); | ||||
| 236 | return (tem == NULL__null ? limit : tem + 1 - base); | ||||
| 237 | } | ||||
| 238 | // Skipping over a single character for a primitive type. | ||||
| 239 | assert(is_java_primitive(decode_signature_char(base[end])), "only primitives expected")do { if (!(is_java_primitive(decode_signature_char(base[end]) ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 239, "assert(" "is_java_primitive(decode_signature_char(base[end]))" ") failed", "only primitives expected"); ::breakpoint(); } } while (0); | ||||
| 240 | return end + 1; | ||||
| 241 | |||||
| 242 | default: | ||||
| 243 | // Skipping over a single character for a primitive type (or void). | ||||
| 244 | assert(!is_reference_type(type), "only primitives or void expected")do { if (!(!is_reference_type(type))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 244, "assert(" "!is_reference_type(type)" ") failed", "only primitives or void expected" ); ::breakpoint(); } } while (0); | ||||
| 245 | return end + 1; | ||||
| 246 | } | ||||
| 247 | } | ||||
| 248 | |||||
| 249 | void SignatureStream::next() { | ||||
| 250 | const Symbol* sig = _signature; | ||||
| 251 | int len = _limit; | ||||
| 252 | if (_end >= len) { set_done(); return; } | ||||
| 253 | _begin = _end; | ||||
| 254 | int ch = sig->char_at(_begin); | ||||
| 255 | if (ch == JVM_SIGNATURE_ENDFUNC) { | ||||
| 256 | assert(_state == _s_method, "must be in method")do { if (!(_state == _s_method)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 256, "assert(" "_state == _s_method" ") failed", "must be in method" ); ::breakpoint(); } } while (0); | ||||
| 257 | _state = _s_method_return; | ||||
| 258 | _begin = ++_end; | ||||
| 259 | if (_end >= len) { set_done(); return; } | ||||
| 260 | ch = sig->char_at(_begin); | ||||
| 261 | } | ||||
| 262 | BasicType bt = decode_signature_char(ch); | ||||
| 263 | assert(ch == type2char(bt), "bad signature char %c/%d", ch, ch)do { if (!(ch == type2char(bt))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 263, "assert(" "ch == type2char(bt)" ") failed", "bad signature char %c/%d" , ch, ch); ::breakpoint(); } } while (0); | ||||
| 264 | _type = bt; | ||||
| 265 | _end = scan_type(bt); | ||||
| 266 | } | ||||
| 267 | |||||
| 268 | int SignatureStream::skip_whole_array_prefix() { | ||||
| 269 | assert(_type == T_ARRAY, "must be")do { if (!(_type == T_ARRAY)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 269, "assert(" "_type == T_ARRAY" ") failed", "must be"); :: breakpoint(); } } while (0); | ||||
| 270 | |||||
| 271 | // we are stripping all levels of T_ARRAY, | ||||
| 272 | // so we must decode the next character | ||||
| 273 | int whole_array_prefix = _array_prefix; | ||||
| 274 | int new_begin = _begin + whole_array_prefix; | ||||
| 275 | _begin = new_begin; | ||||
| 276 | int ch = _signature->char_at(new_begin); | ||||
| 277 | BasicType bt = decode_signature_char(ch); | ||||
| 278 | assert(ch == type2char(bt), "bad signature char %c/%d", ch, ch)do { if (!(ch == type2char(bt))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 278, "assert(" "ch == type2char(bt)" ") failed", "bad signature char %c/%d" , ch, ch); ::breakpoint(); } } while (0); | ||||
| 279 | _type = bt; | ||||
| 280 | assert(bt != T_VOID && bt != T_ARRAY, "bad signature type")do { if (!(bt != T_VOID && bt != T_ARRAY)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 280, "assert(" "bt != T_VOID && bt != T_ARRAY" ") failed" , "bad signature type"); ::breakpoint(); } } while (0); | ||||
| 281 | // Don't bother to re-scan, since it won't change the value of _end. | ||||
| 282 | return whole_array_prefix; | ||||
| 283 | } | ||||
| 284 | |||||
| 285 | bool Signature::is_valid_array_signature(const Symbol* sig) { | ||||
| 286 | assert(sig->utf8_length() > 1, "this should already have been checked")do { if (!(sig->utf8_length() > 1)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 286, "assert(" "sig->utf8_length() > 1" ") failed", "this should already have been checked" ); ::breakpoint(); } } while (0); | ||||
| 287 | assert(sig->char_at(0) == JVM_SIGNATURE_ARRAY, "this should already have been checked")do { if (!(sig->char_at(0) == JVM_SIGNATURE_ARRAY)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 287, "assert(" "sig->char_at(0) == JVM_SIGNATURE_ARRAY" ") failed" , "this should already have been checked"); ::breakpoint(); } } while (0); | ||||
| 288 | // The first character is already checked | ||||
| 289 | int i = 1; | ||||
| 290 | int len = sig->utf8_length(); | ||||
| 291 | // First skip all '['s | ||||
| 292 | while(i < len - 1 && sig->char_at(i) == JVM_SIGNATURE_ARRAY) i++; | ||||
| 293 | |||||
| 294 | // Check type | ||||
| 295 | switch(sig->char_at(i)) { | ||||
| 296 | case JVM_SIGNATURE_BYTE: | ||||
| 297 | case JVM_SIGNATURE_CHAR: | ||||
| 298 | case JVM_SIGNATURE_DOUBLE: | ||||
| 299 | case JVM_SIGNATURE_FLOAT: | ||||
| 300 | case JVM_SIGNATURE_INT: | ||||
| 301 | case JVM_SIGNATURE_LONG: | ||||
| 302 | case JVM_SIGNATURE_SHORT: | ||||
| 303 | case JVM_SIGNATURE_BOOLEAN: | ||||
| 304 | // If it is an array, the type is the last character | ||||
| 305 | return (i + 1 == len); | ||||
| 306 | case JVM_SIGNATURE_CLASS: | ||||
| 307 | // If it is an object, the last character must be a ';' | ||||
| 308 | return sig->char_at(len - 1) == JVM_SIGNATURE_ENDCLASS; | ||||
| 309 | } | ||||
| 310 | return false; | ||||
| 311 | } | ||||
| 312 | |||||
| 313 | BasicType Signature::basic_type(int ch) { | ||||
| 314 | BasicType btcode = decode_signature_char(ch); | ||||
| 315 | if (btcode == 0) return T_ILLEGAL; | ||||
| 316 | return btcode; | ||||
| 317 | } | ||||
| 318 | |||||
| 319 | Symbol* Signature::strip_envelope(const Symbol* signature) { | ||||
| 320 | assert(has_envelope(signature), "precondition")do { if (!(has_envelope(signature))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 320, "assert(" "has_envelope(signature)" ") failed", "precondition" ); ::breakpoint(); } } while (0); | ||||
| 321 | return SymbolTable::new_symbol((char*) signature->bytes() + 1, | ||||
| 322 | signature->utf8_length() - 2); | ||||
| 323 | } | ||||
| 324 | |||||
| 325 | static const int jl_len = 10, object_len = 6, jl_object_len = jl_len + object_len; | ||||
| 326 | static const char jl_str[] = "java/lang/"; | ||||
| 327 | |||||
| 328 | #ifdef ASSERT1 | ||||
| 329 | static bool signature_symbols_sane() { | ||||
| 330 | static bool done; | ||||
| 331 | if (done) return true; | ||||
| 332 | done = true; | ||||
| 333 | // test some tense code that looks for common symbol names: | ||||
| 334 | assert(vmSymbols::java_lang_Object()->utf8_length() == jl_object_len &&do { if (!(vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with (jl_str, jl_len) && vmSymbols::java_lang_Object()-> ends_with("Object", object_len) && vmSymbols::java_lang_Object ()->is_permanent() && vmSymbols::java_lang_String( )->utf8_length() == jl_object_len && vmSymbols::java_lang_String ()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String ()->ends_with("String", object_len) && vmSymbols:: java_lang_String()->is_permanent())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 342, "assert(" "vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_Object()->ends_with(\"Object\", object_len) && vmSymbols::java_lang_Object()->is_permanent() && vmSymbols::java_lang_String()->utf8_length() == jl_object_len && vmSymbols::java_lang_String()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String()->ends_with(\"String\", object_len) && vmSymbols::java_lang_String()->is_permanent()" ") failed", "sanity"); ::breakpoint(); } } while (0) | ||||
| 335 | vmSymbols::java_lang_Object()->starts_with(jl_str, jl_len) &&do { if (!(vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with (jl_str, jl_len) && vmSymbols::java_lang_Object()-> ends_with("Object", object_len) && vmSymbols::java_lang_Object ()->is_permanent() && vmSymbols::java_lang_String( )->utf8_length() == jl_object_len && vmSymbols::java_lang_String ()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String ()->ends_with("String", object_len) && vmSymbols:: java_lang_String()->is_permanent())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 342, "assert(" "vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_Object()->ends_with(\"Object\", object_len) && vmSymbols::java_lang_Object()->is_permanent() && vmSymbols::java_lang_String()->utf8_length() == jl_object_len && vmSymbols::java_lang_String()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String()->ends_with(\"String\", object_len) && vmSymbols::java_lang_String()->is_permanent()" ") failed", "sanity"); ::breakpoint(); } } while (0) | ||||
| 336 | vmSymbols::java_lang_Object()->ends_with("Object", object_len) &&do { if (!(vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with (jl_str, jl_len) && vmSymbols::java_lang_Object()-> ends_with("Object", object_len) && vmSymbols::java_lang_Object ()->is_permanent() && vmSymbols::java_lang_String( )->utf8_length() == jl_object_len && vmSymbols::java_lang_String ()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String ()->ends_with("String", object_len) && vmSymbols:: java_lang_String()->is_permanent())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 342, "assert(" "vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_Object()->ends_with(\"Object\", object_len) && vmSymbols::java_lang_Object()->is_permanent() && vmSymbols::java_lang_String()->utf8_length() == jl_object_len && vmSymbols::java_lang_String()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String()->ends_with(\"String\", object_len) && vmSymbols::java_lang_String()->is_permanent()" ") failed", "sanity"); ::breakpoint(); } } while (0) | ||||
| 337 | vmSymbols::java_lang_Object()->is_permanent() &&do { if (!(vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with (jl_str, jl_len) && vmSymbols::java_lang_Object()-> ends_with("Object", object_len) && vmSymbols::java_lang_Object ()->is_permanent() && vmSymbols::java_lang_String( )->utf8_length() == jl_object_len && vmSymbols::java_lang_String ()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String ()->ends_with("String", object_len) && vmSymbols:: java_lang_String()->is_permanent())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 342, "assert(" "vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_Object()->ends_with(\"Object\", object_len) && vmSymbols::java_lang_Object()->is_permanent() && vmSymbols::java_lang_String()->utf8_length() == jl_object_len && vmSymbols::java_lang_String()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String()->ends_with(\"String\", object_len) && vmSymbols::java_lang_String()->is_permanent()" ") failed", "sanity"); ::breakpoint(); } } while (0) | ||||
| 338 | vmSymbols::java_lang_String()->utf8_length() == jl_object_len &&do { if (!(vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with (jl_str, jl_len) && vmSymbols::java_lang_Object()-> ends_with("Object", object_len) && vmSymbols::java_lang_Object ()->is_permanent() && vmSymbols::java_lang_String( )->utf8_length() == jl_object_len && vmSymbols::java_lang_String ()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String ()->ends_with("String", object_len) && vmSymbols:: java_lang_String()->is_permanent())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 342, "assert(" "vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_Object()->ends_with(\"Object\", object_len) && vmSymbols::java_lang_Object()->is_permanent() && vmSymbols::java_lang_String()->utf8_length() == jl_object_len && vmSymbols::java_lang_String()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String()->ends_with(\"String\", object_len) && vmSymbols::java_lang_String()->is_permanent()" ") failed", "sanity"); ::breakpoint(); } } while (0) | ||||
| 339 | vmSymbols::java_lang_String()->starts_with(jl_str, jl_len) &&do { if (!(vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with (jl_str, jl_len) && vmSymbols::java_lang_Object()-> ends_with("Object", object_len) && vmSymbols::java_lang_Object ()->is_permanent() && vmSymbols::java_lang_String( )->utf8_length() == jl_object_len && vmSymbols::java_lang_String ()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String ()->ends_with("String", object_len) && vmSymbols:: java_lang_String()->is_permanent())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 342, "assert(" "vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_Object()->ends_with(\"Object\", object_len) && vmSymbols::java_lang_Object()->is_permanent() && vmSymbols::java_lang_String()->utf8_length() == jl_object_len && vmSymbols::java_lang_String()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String()->ends_with(\"String\", object_len) && vmSymbols::java_lang_String()->is_permanent()" ") failed", "sanity"); ::breakpoint(); } } while (0) | ||||
| 340 | vmSymbols::java_lang_String()->ends_with("String", object_len) &&do { if (!(vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with (jl_str, jl_len) && vmSymbols::java_lang_Object()-> ends_with("Object", object_len) && vmSymbols::java_lang_Object ()->is_permanent() && vmSymbols::java_lang_String( )->utf8_length() == jl_object_len && vmSymbols::java_lang_String ()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String ()->ends_with("String", object_len) && vmSymbols:: java_lang_String()->is_permanent())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 342, "assert(" "vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_Object()->ends_with(\"Object\", object_len) && vmSymbols::java_lang_Object()->is_permanent() && vmSymbols::java_lang_String()->utf8_length() == jl_object_len && vmSymbols::java_lang_String()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String()->ends_with(\"String\", object_len) && vmSymbols::java_lang_String()->is_permanent()" ") failed", "sanity"); ::breakpoint(); } } while (0) | ||||
| 341 | vmSymbols::java_lang_String()->is_permanent(),do { if (!(vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with (jl_str, jl_len) && vmSymbols::java_lang_Object()-> ends_with("Object", object_len) && vmSymbols::java_lang_Object ()->is_permanent() && vmSymbols::java_lang_String( )->utf8_length() == jl_object_len && vmSymbols::java_lang_String ()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String ()->ends_with("String", object_len) && vmSymbols:: java_lang_String()->is_permanent())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 342, "assert(" "vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_Object()->ends_with(\"Object\", object_len) && vmSymbols::java_lang_Object()->is_permanent() && vmSymbols::java_lang_String()->utf8_length() == jl_object_len && vmSymbols::java_lang_String()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String()->ends_with(\"String\", object_len) && vmSymbols::java_lang_String()->is_permanent()" ") failed", "sanity"); ::breakpoint(); } } while (0) | ||||
| 342 | "sanity")do { if (!(vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with (jl_str, jl_len) && vmSymbols::java_lang_Object()-> ends_with("Object", object_len) && vmSymbols::java_lang_Object ()->is_permanent() && vmSymbols::java_lang_String( )->utf8_length() == jl_object_len && vmSymbols::java_lang_String ()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String ()->ends_with("String", object_len) && vmSymbols:: java_lang_String()->is_permanent())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 342, "assert(" "vmSymbols::java_lang_Object()->utf8_length() == jl_object_len && vmSymbols::java_lang_Object()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_Object()->ends_with(\"Object\", object_len) && vmSymbols::java_lang_Object()->is_permanent() && vmSymbols::java_lang_String()->utf8_length() == jl_object_len && vmSymbols::java_lang_String()->starts_with(jl_str, jl_len) && vmSymbols::java_lang_String()->ends_with(\"String\", object_len) && vmSymbols::java_lang_String()->is_permanent()" ") failed", "sanity"); ::breakpoint(); } } while (0); | ||||
| 343 | return true; | ||||
| 344 | } | ||||
| 345 | #endif //ASSERT | ||||
| 346 | |||||
| 347 | // returns a symbol; the caller is responsible for decrementing it | ||||
| 348 | Symbol* SignatureStream::find_symbol() { | ||||
| 349 | // Create a symbol from for string _begin _end | ||||
| 350 | int begin = raw_symbol_begin(); | ||||
| 351 | int end = raw_symbol_end(); | ||||
| 352 | |||||
| 353 | const char* symbol_chars = (const char*)_signature->base() + begin; | ||||
| 354 | int len = end - begin; | ||||
| 355 | |||||
| 356 | // Quick check for common symbols in signatures | ||||
| 357 | assert(signature_symbols_sane(), "incorrect signature sanity check")do { if (!(signature_symbols_sane())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 357, "assert(" "signature_symbols_sane()" ") failed", "incorrect signature sanity check" ); ::breakpoint(); } } while (0); | ||||
| 358 | if (len == jl_object_len && | ||||
| 359 | memcmp(symbol_chars, jl_str, jl_len) == 0) { | ||||
| 360 | if (memcmp("String", symbol_chars + jl_len, object_len) == 0) { | ||||
| 361 | return vmSymbols::java_lang_String(); | ||||
| 362 | } else if (memcmp("Object", symbol_chars + jl_len, object_len) == 0) { | ||||
| 363 | return vmSymbols::java_lang_Object(); | ||||
| 364 | } | ||||
| 365 | } | ||||
| 366 | |||||
| 367 | Symbol* name = _previous_name; | ||||
| 368 | if (name->equals(symbol_chars, len)) { | ||||
| 369 | return name; | ||||
| 370 | } | ||||
| 371 | |||||
| 372 | // Save names for cleaning up reference count at the end of | ||||
| 373 | // SignatureStream scope. | ||||
| 374 | name = SymbolTable::new_symbol(symbol_chars, len); | ||||
| 375 | |||||
| 376 | // Only allocate the GrowableArray for the _names buffer if more than | ||||
| 377 | // one name is being processed in the signature. | ||||
| 378 | if (!_previous_name->is_permanent()) { | ||||
| 379 | if (_names == NULL__null) { | ||||
| 380 | _names = new GrowableArray<Symbol*>(10); | ||||
| 381 | } | ||||
| 382 | _names->push(_previous_name); | ||||
| 383 | } | ||||
| 384 | _previous_name = name; | ||||
| 385 | return name; | ||||
| 386 | } | ||||
| 387 | |||||
| 388 | Klass* SignatureStream::as_klass(Handle class_loader, Handle protection_domain, | ||||
| 389 | FailureMode failure_mode, TRAPSJavaThread* __the_thread__) { | ||||
| 390 | if (!is_reference()) { | ||||
| 391 | return NULL__null; | ||||
| 392 | } | ||||
| 393 | Symbol* name = as_symbol(); | ||||
| 394 | Klass* k = NULL__null; | ||||
| 395 | if (failure_mode == ReturnNull) { | ||||
| 396 | // Note: SD::resolve_or_null returns NULL for most failure modes, | ||||
| 397 | // but not all. Circularity errors, invalid PDs, etc., throw. | ||||
| 398 | k = SystemDictionary::resolve_or_null(name, class_loader, protection_domain, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||
| 399 | } else if (failure_mode == CachedOrNull) { | ||||
| 400 | NoSafepointVerifier nsv; // no loading, now, we mean it! | ||||
| 401 | assert(!HAS_PENDING_EXCEPTION, "")do { if (!(!(((ThreadShadow*)__the_thread__)->has_pending_exception ()))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 401, "assert(" "!(((ThreadShadow*)__the_thread__)->has_pending_exception())" ") failed", ""); ::breakpoint(); } } while (0); | ||||
| 402 | k = SystemDictionary::find_instance_klass(name, class_loader, protection_domain); | ||||
| 403 | // SD::find does not trigger loading, so there should be no throws | ||||
| 404 | // Still, bad things can happen, so we CHECK_NULL and ask callers | ||||
| 405 | // to do likewise. | ||||
| 406 | return k; | ||||
| 407 | } else { | ||||
| 408 | // The only remaining failure mode is NCDFError. | ||||
| 409 | // The test here allows for an additional mode CNFException | ||||
| 410 | // if callers need to request the reflective error instead. | ||||
| 411 | bool throw_error = (failure_mode == NCDFError); | ||||
| 412 | k = SystemDictionary::resolve_or_fail(name, class_loader, protection_domain, throw_error, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||
| 413 | } | ||||
| 414 | |||||
| 415 | return k; | ||||
| 416 | } | ||||
| 417 | |||||
| 418 | oop SignatureStream::as_java_mirror(Handle class_loader, Handle protection_domain, | ||||
| 419 | FailureMode failure_mode, TRAPSJavaThread* __the_thread__) { | ||||
| 420 | if (!is_reference()) { | ||||
| 421 | return Universe::java_mirror(type()); | ||||
| 422 | } | ||||
| 423 | Klass* klass = as_klass(class_loader, protection_domain, failure_mode, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||
| 424 | if (klass == NULL__null) { | ||||
| 425 | return NULL__null; | ||||
| 426 | } | ||||
| 427 | return klass->java_mirror(); | ||||
| 428 | } | ||||
| 429 | |||||
| 430 | void SignatureStream::skip_to_return_type() { | ||||
| 431 | while (!at_return_type()) { | ||||
| 432 | next(); | ||||
| 433 | } | ||||
| 434 | } | ||||
| 435 | |||||
| 436 | ResolvingSignatureStream::ResolvingSignatureStream(Symbol* signature, | ||||
| 437 | Handle class_loader, | ||||
| 438 | Handle protection_domain, | ||||
| 439 | bool is_method) | ||||
| 440 | : SignatureStream(signature, is_method), | ||||
| 441 | _class_loader(class_loader), _protection_domain(protection_domain) | ||||
| 442 | { | ||||
| 443 | initialize_load_origin(NULL__null); | ||||
| 444 | } | ||||
| 445 | |||||
| 446 | ResolvingSignatureStream::ResolvingSignatureStream(Symbol* signature, Klass* load_origin, bool is_method) | ||||
| 447 | : SignatureStream(signature, is_method) | ||||
| 448 | { | ||||
| 449 | assert(load_origin != NULL, "")do { if (!(load_origin != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 449, "assert(" "load_origin != __null" ") failed", ""); ::breakpoint (); } } while (0); | ||||
| 450 | initialize_load_origin(load_origin); | ||||
| 451 | } | ||||
| 452 | |||||
| 453 | ResolvingSignatureStream::ResolvingSignatureStream(const Method* method) | ||||
| 454 | : SignatureStream(method->signature(), true) | ||||
| 455 | { | ||||
| 456 | initialize_load_origin(method->method_holder()); | ||||
| 457 | } | ||||
| 458 | |||||
| 459 | ResolvingSignatureStream::ResolvingSignatureStream(fieldDescriptor& field) | ||||
| 460 | : SignatureStream(field.signature(), false) | ||||
| 461 | { | ||||
| 462 | initialize_load_origin(field.field_holder()); | ||||
| 463 | } | ||||
| 464 | |||||
| 465 | void ResolvingSignatureStream::cache_handles() { | ||||
| 466 | assert(_load_origin != NULL, "")do { if (!(_load_origin != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 466, "assert(" "_load_origin != __null" ") failed", ""); :: breakpoint(); } } while (0); | ||||
| 467 | JavaThread* current = JavaThread::current(); | ||||
| 468 | _class_loader = Handle(current, _load_origin->class_loader()); | ||||
| 469 | _protection_domain = Handle(current, _load_origin->protection_domain()); | ||||
| 470 | } | ||||
| 471 | |||||
| 472 | Klass* ResolvingSignatureStream::as_klass_if_loaded(TRAPSJavaThread* __the_thread__) { | ||||
| 473 | Klass* klass = as_klass(CachedOrNull, THREAD__the_thread__); | ||||
| 474 | // SD::find does not trigger loading, so there should be no throws | ||||
| 475 | // Still, bad things can happen, so we CHECK_NULL and ask callers | ||||
| 476 | // to do likewise. | ||||
| 477 | if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) { | ||||
| 478 | CLEAR_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_exception( )); | ||||
| 479 | } | ||||
| 480 | return klass; | ||||
| 481 | } | ||||
| 482 | |||||
| 483 | #ifdef ASSERT1 | ||||
| 484 | |||||
| 485 | extern bool signature_constants_sane(); // called from basic_types_init() | ||||
| 486 | |||||
| 487 | bool signature_constants_sane() { | ||||
| 488 | // for the lookup table, test every 8-bit code point, and then some: | ||||
| 489 | for (int i = -256; i <= 256; i++) { | ||||
| 490 | int btcode = 0; | ||||
| 491 | switch (i) { | ||||
| 492 | #define EACH_SIG(ch, bt, ignore) \ | ||||
| 493 | case ch: { btcode = bt; break; } | ||||
| 494 | SIGNATURE_TYPES_DO(EACH_SIG, ignore)EACH_SIG(JVM_SIGNATURE_BOOLEAN, T_BOOLEAN, ignore) EACH_SIG(JVM_SIGNATURE_CHAR , T_CHAR, ignore) EACH_SIG(JVM_SIGNATURE_FLOAT, T_FLOAT, ignore ) EACH_SIG(JVM_SIGNATURE_DOUBLE, T_DOUBLE, ignore) EACH_SIG(JVM_SIGNATURE_BYTE , T_BYTE, ignore) EACH_SIG(JVM_SIGNATURE_SHORT, T_SHORT, ignore ) EACH_SIG(JVM_SIGNATURE_INT, T_INT, ignore) EACH_SIG(JVM_SIGNATURE_LONG , T_LONG, ignore) EACH_SIG(JVM_SIGNATURE_CLASS, T_OBJECT, ignore ) EACH_SIG(JVM_SIGNATURE_ARRAY, T_ARRAY, ignore) EACH_SIG(JVM_SIGNATURE_VOID , T_VOID, ignore) | ||||
| 495 | #undef EACH_SIG | ||||
| 496 | } | ||||
| 497 | int btc = decode_signature_char(i); | ||||
| 498 | assert(btc == btcode, "misconfigured table: %d => %d not %d", i, btc, btcode)do { if (!(btc == btcode)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.cpp" , 498, "assert(" "btc == btcode" ") failed", "misconfigured table: %d => %d not %d" , i, btc, btcode); ::breakpoint(); } } while (0); | ||||
| 499 | } | ||||
| 500 | return true; | ||||
| 501 | } | ||||
| 502 | |||||
| 503 | bool SignatureVerifier::is_valid_method_signature(Symbol* sig) { | ||||
| 504 | const char* method_sig = (const char*)sig->bytes(); | ||||
| 505 | ssize_t len = sig->utf8_length(); | ||||
| 506 | ssize_t index = 0; | ||||
| 507 | if (method_sig != NULL__null && len > 1 && method_sig[index] == JVM_SIGNATURE_FUNC) { | ||||
| 508 | ++index; | ||||
| 509 | while (index < len && method_sig[index] != JVM_SIGNATURE_ENDFUNC) { | ||||
| 510 | ssize_t res = is_valid_type(&method_sig[index], len - index); | ||||
| 511 | if (res == -1) { | ||||
| 512 | return false; | ||||
| 513 | } else { | ||||
| 514 | index += res; | ||||
| 515 | } | ||||
| 516 | } | ||||
| 517 | if (index < len && method_sig[index] == JVM_SIGNATURE_ENDFUNC) { | ||||
| 518 | // check the return type | ||||
| 519 | ++index; | ||||
| 520 | return (is_valid_type(&method_sig[index], len - index) == (len - index)); | ||||
| 521 | } | ||||
| 522 | } | ||||
| 523 | return false; | ||||
| 524 | } | ||||
| 525 | |||||
| 526 | bool SignatureVerifier::is_valid_type_signature(Symbol* sig) { | ||||
| 527 | const char* type_sig = (const char*)sig->bytes(); | ||||
| 528 | ssize_t len = sig->utf8_length(); | ||||
| 529 | return (type_sig != NULL__null && len >= 1 && | ||||
| 530 | (is_valid_type(type_sig, len) == len)); | ||||
| 531 | } | ||||
| 532 | |||||
| 533 | // Checks to see if the type (not to go beyond 'limit') refers to a valid type. | ||||
| 534 | // Returns -1 if it is not, or the index of the next character that is not part | ||||
| 535 | // of the type. The type encoding may end before 'limit' and that's ok. | ||||
| 536 | ssize_t SignatureVerifier::is_valid_type(const char* type, ssize_t limit) { | ||||
| 537 | ssize_t index = 0; | ||||
| 538 | |||||
| 539 | // Iterate over any number of array dimensions | ||||
| 540 | while (index < limit && type[index] == JVM_SIGNATURE_ARRAY) ++index; | ||||
| 541 | if (index >= limit) { | ||||
| 542 | return -1; | ||||
| 543 | } | ||||
| 544 | switch (type[index]) { | ||||
| 545 | case JVM_SIGNATURE_BYTE: | ||||
| 546 | case JVM_SIGNATURE_CHAR: | ||||
| 547 | case JVM_SIGNATURE_FLOAT: | ||||
| 548 | case JVM_SIGNATURE_DOUBLE: | ||||
| 549 | case JVM_SIGNATURE_INT: | ||||
| 550 | case JVM_SIGNATURE_LONG: | ||||
| 551 | case JVM_SIGNATURE_SHORT: | ||||
| 552 | case JVM_SIGNATURE_BOOLEAN: | ||||
| 553 | case JVM_SIGNATURE_VOID: | ||||
| 554 | return index + 1; | ||||
| 555 | case JVM_SIGNATURE_CLASS: | ||||
| 556 | for (index = index + 1; index < limit; ++index) { | ||||
| 557 | char c = type[index]; | ||||
| 558 | switch (c) { | ||||
| 559 | case JVM_SIGNATURE_ENDCLASS: | ||||
| 560 | return index + 1; | ||||
| 561 | case '\0': case JVM_SIGNATURE_DOT: case JVM_SIGNATURE_ARRAY: | ||||
| 562 | return -1; | ||||
| 563 | default: ; // fall through | ||||
| 564 | } | ||||
| 565 | } | ||||
| 566 | // fall through | ||||
| 567 | default: ; // fall through | ||||
| 568 | } | ||||
| 569 | return -1; | ||||
| 570 | } | ||||
| 571 | |||||
| 572 | #endif // ASSERT |
| 1 | /* | |||
| 2 | * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. | |||
| 3 | * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. | |||
| 4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |||
| 5 | * | |||
| 6 | * This code is free software; you can redistribute it and/or modify it | |||
| 7 | * under the terms of the GNU General Public License version 2 only, as | |||
| 8 | * published by the Free Software Foundation. | |||
| 9 | * | |||
| 10 | * This code is distributed in the hope that it will be useful, but WITHOUT | |||
| 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |||
| 13 | * version 2 for more details (a copy is included in the LICENSE file that | |||
| 14 | * accompanied this code). | |||
| 15 | * | |||
| 16 | * You should have received a copy of the GNU General Public License version | |||
| 17 | * 2 along with this work; if not, write to the Free Software Foundation, | |||
| 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |||
| 19 | * | |||
| 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |||
| 21 | * or visit www.oracle.com if you need additional information or have any | |||
| 22 | * questions. | |||
| 23 | * | |||
| 24 | */ | |||
| 25 | ||||
| 26 | #ifndef SHARE_RUNTIME_SIGNATURE_HPP | |||
| 27 | #define SHARE_RUNTIME_SIGNATURE_HPP | |||
| 28 | ||||
| 29 | #include "memory/allocation.hpp" | |||
| 30 | #include "oops/method.hpp" | |||
| 31 | ||||
| 32 | ||||
| 33 | // Static routines and parsing loops for processing field and method | |||
| 34 | // descriptors. In the HotSpot sources we call them "signatures". | |||
| 35 | // | |||
| 36 | // A SignatureStream iterates over a Java descriptor (or parts of it). | |||
| 37 | // The syntax is documented in the Java Virtual Machine Specification, | |||
| 38 | // section 4.3. | |||
| 39 | // | |||
| 40 | // The syntax may be summarized as follows: | |||
| 41 | // | |||
| 42 | // MethodType: '(' {FieldType}* ')' (FieldType | 'V') | |||
| 43 | // FieldType: PrimitiveType | ObjectType | ArrayType | |||
| 44 | // PrimitiveType: 'B' | 'C' | 'D' | 'F' | 'I' | 'J' | 'S' | 'Z' | |||
| 45 | // ObjectType: 'L' ClassName ';' | ArrayType | |||
| 46 | // ArrayType: '[' FieldType | |||
| 47 | // ClassName: {UnqualifiedName '/'}* UnqualifiedName | |||
| 48 | // UnqualifiedName: NameChar {NameChar}* | |||
| 49 | // NameChar: ANY_CHAR_EXCEPT('/' | '.' | ';' | '[') | |||
| 50 | // | |||
| 51 | // All of the concrete characters in the above grammar are given | |||
| 52 | // standard manifest constant names of the form JVM_SIGNATURE_x. | |||
| 53 | // Executable code uses these constant names in preference to raw | |||
| 54 | // character constants. Comments and assertion code sometimes use | |||
| 55 | // the raw character constants for brevity. | |||
| 56 | // | |||
| 57 | // The primitive field types (like 'I') correspond 1-1 with type codes | |||
| 58 | // (like T_INT) which form part of the specification of the 'newarray' | |||
| 59 | // instruction (JVMS 6.5, section on newarray). These type codes are | |||
| 60 | // widely used in the HotSpot code. They are joined by ad hoc codes | |||
| 61 | // like T_OBJECT and T_ARRAY (defined in HotSpot but not in the JVMS) | |||
| 62 | // so that each "basic type" of field descriptor (or void return type) | |||
| 63 | // has a corresponding T_x code. Thus, while T_x codes play a very | |||
| 64 | // minor role in the JVMS, they play a major role in the HotSpot | |||
| 65 | // sources. There are fewer than 16 such "basic types", so they fit | |||
| 66 | // nicely into bitfields. | |||
| 67 | // | |||
| 68 | // The syntax of ClassName overlaps slightly with the descriptor | |||
| 69 | // syntaxes. The strings "I" and "(I)V" are both class names | |||
| 70 | // *and* descriptors. If a class name contains any character other | |||
| 71 | // than "BCDFIJSZ()V" it cannot be confused with a descriptor. | |||
| 72 | // Class names inside of descriptors are always contained in an | |||
| 73 | // "envelope" syntax which starts with 'L' and ends with ';'. | |||
| 74 | // | |||
| 75 | // As a confounding factor, array types report their type name strings | |||
| 76 | // in descriptor format. These name strings are easy to recognize, | |||
| 77 | // since they begin with '['. For this reason some API points on | |||
| 78 | // HotSpot look for array descriptors as well as proper class names. | |||
| 79 | // | |||
| 80 | // For historical reasons some API points that accept class names and | |||
| 81 | // array names also look for class names wrapped inside an envelope | |||
| 82 | // (like "LFoo;") and unwrap them on the fly (to a name like "Foo"). | |||
| 83 | ||||
| 84 | class Signature : AllStatic { | |||
| 85 | private: | |||
| 86 | static bool is_valid_array_signature(const Symbol* sig); | |||
| 87 | ||||
| 88 | public: | |||
| 89 | ||||
| 90 | // Returns the basic type of a field signature (or T_VOID for "V"). | |||
| 91 | // Assumes the signature is a valid field descriptor. | |||
| 92 | // Do not apply this function to class names or method signatures. | |||
| 93 | static BasicType basic_type(const Symbol* signature) { | |||
| 94 | return basic_type(signature->char_at(0)); | |||
| 95 | } | |||
| 96 | ||||
| 97 | // Returns T_ILLEGAL for an illegal signature char. | |||
| 98 | static BasicType basic_type(int ch); | |||
| 99 | ||||
| 100 | // Assuming it is either a class name or signature, | |||
| 101 | // determine if it in fact cannot be a class name. | |||
| 102 | // This means it either starts with '[' or ends with ';' | |||
| 103 | static bool not_class_name(const Symbol* signature) { | |||
| 104 | return (signature->starts_with(JVM_SIGNATURE_ARRAY) || | |||
| 105 | signature->ends_with(JVM_SIGNATURE_ENDCLASS)); | |||
| 106 | } | |||
| 107 | ||||
| 108 | // Assuming it is either a class name or signature, | |||
| 109 | // determine if it in fact is an array descriptor. | |||
| 110 | static bool is_array(const Symbol* signature) { | |||
| 111 | return (signature->utf8_length() > 1 && | |||
| 112 | signature->char_at(0) == JVM_SIGNATURE_ARRAY && | |||
| 113 | is_valid_array_signature(signature)); | |||
| 114 | } | |||
| 115 | ||||
| 116 | // Assuming it is either a class name or signature, | |||
| 117 | // determine if it contains a class name plus ';'. | |||
| 118 | static bool has_envelope(const Symbol* signature) { | |||
| 119 | return ((signature->utf8_length() > 0) && | |||
| 120 | signature->ends_with(JVM_SIGNATURE_ENDCLASS) && | |||
| 121 | has_envelope(signature->char_at(0))); | |||
| 122 | } | |||
| 123 | ||||
| 124 | // Determine if this signature char introduces an | |||
| 125 | // envelope, which is a class name plus ';'. | |||
| 126 | static bool has_envelope(char signature_char) { | |||
| 127 | return (signature_char == JVM_SIGNATURE_CLASS); | |||
| 128 | } | |||
| 129 | ||||
| 130 | // Assuming has_envelope is true, return the symbol | |||
| 131 | // inside the envelope, by stripping 'L' and ';'. | |||
| 132 | // Caller is responsible for decrementing the newly created | |||
| 133 | // Symbol's refcount, use TempNewSymbol. | |||
| 134 | static Symbol* strip_envelope(const Symbol* signature); | |||
| 135 | ||||
| 136 | // Assuming it's either a field or method descriptor, determine | |||
| 137 | // whether it is in fact a method descriptor: | |||
| 138 | static bool is_method(const Symbol* signature) { | |||
| 139 | return signature->starts_with(JVM_SIGNATURE_FUNC); | |||
| 140 | } | |||
| 141 | ||||
| 142 | // Assuming it's a method signature, determine if it must | |||
| 143 | // return void. | |||
| 144 | static bool is_void_method(const Symbol* signature) { | |||
| 145 | assert(is_method(signature), "signature is not for a method")do { if (!(is_method(signature))) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.hpp" , 145, "assert(" "is_method(signature)" ") failed", "signature is not for a method" ); ::breakpoint(); } } while (0); | |||
| 146 | return signature->ends_with(JVM_SIGNATURE_VOID); | |||
| 147 | } | |||
| 148 | }; | |||
| 149 | ||||
| 150 | // A SignatureIterator uses a SignatureStream to produce BasicType | |||
| 151 | // results, discarding class names. This means it can be accelerated | |||
| 152 | // using a fingerprint mechanism, in many cases, without loss of type | |||
| 153 | // information. The FingerPrinter class computes and caches this | |||
| 154 | // reduced information for faster iteration. | |||
| 155 | ||||
| 156 | class SignatureIterator: public ResourceObj { | |||
| 157 | public: | |||
| 158 | typedef uint64_t fingerprint_t; | |||
| 159 | ||||
| 160 | protected: | |||
| 161 | Symbol* _signature; // the signature to iterate over | |||
| 162 | BasicType _return_type; | |||
| 163 | fingerprint_t _fingerprint; | |||
| 164 | ||||
| 165 | public: | |||
| 166 | // Definitions used in generating and iterating the | |||
| 167 | // bit field form of the signature generated by the | |||
| 168 | // Fingerprinter. | |||
| 169 | enum { | |||
| 170 | fp_static_feature_size = 1, | |||
| 171 | fp_is_static_bit = 1, | |||
| 172 | ||||
| 173 | fp_result_feature_size = 4, | |||
| 174 | fp_result_feature_mask = right_n_bits(fp_result_feature_size)((((fp_result_feature_size) >= BitsPerWord) ? 0 : (OneBit << (fp_result_feature_size))) - 1), | |||
| 175 | fp_parameter_feature_size = 4, | |||
| 176 | fp_parameter_feature_mask = right_n_bits(fp_parameter_feature_size)((((fp_parameter_feature_size) >= BitsPerWord) ? 0 : (OneBit << (fp_parameter_feature_size))) - 1), | |||
| 177 | ||||
| 178 | fp_parameters_done = 0, // marker for end of parameters (must be zero) | |||
| 179 | ||||
| 180 | // Parameters take up full wordsize, minus the result and static bit fields. | |||
| 181 | // Since fp_parameters_done is zero, termination field arises from shifting | |||
| 182 | // in zero bits, and therefore occupies no extra space. | |||
| 183 | // The sentinel value is all-zero-bits, which is impossible for a true | |||
| 184 | // fingerprint, since at least the result field will be non-zero. | |||
| 185 | fp_max_size_of_parameters = ((BitsPerLong | |||
| 186 | - (fp_result_feature_size + fp_static_feature_size)) | |||
| 187 | / fp_parameter_feature_size) | |||
| 188 | }; | |||
| 189 | ||||
| 190 | static bool fp_is_valid_type(BasicType type, bool for_return_type = false); | |||
| 191 | ||||
| 192 | // Sentinel values are zero and not-zero (-1). | |||
| 193 | // No need to protect the sign bit, since every valid return type is non-zero | |||
| 194 | // (even T_VOID), and there are no valid parameter fields which are 0xF (T_VOID). | |||
| 195 | static fingerprint_t zero_fingerprint() { return (fingerprint_t)0; } | |||
| 196 | static fingerprint_t overflow_fingerprint() { return ~(fingerprint_t)0; } | |||
| 197 | static bool fp_is_valid(fingerprint_t fingerprint) { | |||
| 198 | return (fingerprint != zero_fingerprint()) && (fingerprint != overflow_fingerprint()); | |||
| 199 | } | |||
| 200 | ||||
| 201 | // Constructors | |||
| 202 | SignatureIterator(Symbol* signature, fingerprint_t fingerprint = zero_fingerprint()) { | |||
| 203 | _signature = signature; | |||
| 204 | _return_type = T_ILLEGAL; // sentinel value for uninitialized | |||
| 205 | _fingerprint = zero_fingerprint(); | |||
| 206 | if (fingerprint != _fingerprint) { | |||
| 207 | set_fingerprint(fingerprint); | |||
| 208 | } | |||
| 209 | } | |||
| 210 | ||||
| 211 | // If the fingerprint is present, we can use an accelerated loop. | |||
| 212 | void set_fingerprint(fingerprint_t fingerprint); | |||
| 213 | ||||
| 214 | // Returns the set fingerprint, or zero_fingerprint() | |||
| 215 | // if none has been set already. | |||
| 216 | fingerprint_t fingerprint() const { return _fingerprint; } | |||
| 217 | ||||
| 218 | // Iteration | |||
| 219 | // Hey look: There are no virtual methods in this class. | |||
| 220 | // So how is it customized? By calling do_parameters_on | |||
| 221 | // an object which answers to "do_type(BasicType)". | |||
| 222 | // By convention, this object is in the subclass | |||
| 223 | // itself, so the call is "do_parameters_on(this)". | |||
| 224 | // The effect of this is to inline the parsing loop | |||
| 225 | // everywhere "do_parameters_on" is called. | |||
| 226 | // If there is a valid fingerprint in the object, | |||
| 227 | // an improved loop is called which just unpacks the | |||
| 228 | // bitfields from the fingerprint. Otherwise, the | |||
| 229 | // symbol is parsed. | |||
| 230 | template<typename T> inline void do_parameters_on(T* callback); // iterates over parameters only | |||
| 231 | BasicType return_type(); // computes the value on the fly if necessary | |||
| 232 | ||||
| 233 | static bool fp_is_static(fingerprint_t fingerprint) { | |||
| 234 | assert(fp_is_valid(fingerprint), "invalid fingerprint")do { if (!(fp_is_valid(fingerprint))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.hpp" , 234, "assert(" "fp_is_valid(fingerprint)" ") failed", "invalid fingerprint" ); ::breakpoint(); } } while (0); | |||
| 235 | return fingerprint & fp_is_static_bit; | |||
| 236 | } | |||
| 237 | static BasicType fp_return_type(fingerprint_t fingerprint) { | |||
| 238 | assert(fp_is_valid(fingerprint), "invalid fingerprint")do { if (!(fp_is_valid(fingerprint))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.hpp" , 238, "assert(" "fp_is_valid(fingerprint)" ") failed", "invalid fingerprint" ); ::breakpoint(); } } while (0); | |||
| 239 | return (BasicType) ((fingerprint >> fp_static_feature_size) & fp_result_feature_mask); | |||
| 240 | } | |||
| 241 | static fingerprint_t fp_start_parameters(fingerprint_t fingerprint) { | |||
| 242 | assert(fp_is_valid(fingerprint), "invalid fingerprint")do { if (!(fp_is_valid(fingerprint))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.hpp" , 242, "assert(" "fp_is_valid(fingerprint)" ") failed", "invalid fingerprint" ); ::breakpoint(); } } while (0); | |||
| 243 | return fingerprint >> (fp_static_feature_size + fp_result_feature_size); | |||
| 244 | } | |||
| 245 | static BasicType fp_next_parameter(fingerprint_t& mask) { | |||
| 246 | int result = (mask & fp_parameter_feature_mask); | |||
| 247 | mask >>= fp_parameter_feature_size; | |||
| 248 | return (BasicType) result; | |||
| 249 | } | |||
| 250 | }; | |||
| 251 | ||||
| 252 | ||||
| 253 | // Specialized SignatureIterators: Used to compute signature specific values. | |||
| 254 | ||||
| 255 | class SignatureTypeNames : public SignatureIterator { | |||
| 256 | protected: | |||
| 257 | virtual void type_name(const char* name) = 0; | |||
| 258 | ||||
| 259 | friend class SignatureIterator; // so do_parameters_on can call do_type | |||
| 260 | void do_type(BasicType type) { | |||
| 261 | switch (type) { | |||
| 262 | case T_BOOLEAN: type_name("jboolean"); break; | |||
| 263 | case T_CHAR: type_name("jchar" ); break; | |||
| 264 | case T_FLOAT: type_name("jfloat" ); break; | |||
| 265 | case T_DOUBLE: type_name("jdouble" ); break; | |||
| 266 | case T_BYTE: type_name("jbyte" ); break; | |||
| 267 | case T_SHORT: type_name("jshort" ); break; | |||
| 268 | case T_INT: type_name("jint" ); break; | |||
| 269 | case T_LONG: type_name("jlong" ); break; | |||
| 270 | case T_VOID: type_name("void" ); break; | |||
| 271 | case T_ARRAY: | |||
| 272 | case T_OBJECT: type_name("jobject" ); break; | |||
| 273 | default: ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.hpp" , 273); ::breakpoint(); } while (0); | |||
| 274 | } | |||
| 275 | } | |||
| 276 | ||||
| 277 | public: | |||
| 278 | SignatureTypeNames(Symbol* signature) : SignatureIterator(signature) {} | |||
| 279 | }; | |||
| 280 | ||||
| 281 | ||||
| 282 | // Specialized SignatureIterator: Used to compute the argument size. | |||
| 283 | ||||
| 284 | class ArgumentSizeComputer: public SignatureIterator { | |||
| 285 | private: | |||
| 286 | int _size; | |||
| 287 | friend class SignatureIterator; // so do_parameters_on can call do_type | |||
| 288 | void do_type(BasicType type) { _size += parameter_type_word_count(type); } | |||
| 289 | public: | |||
| 290 | ArgumentSizeComputer(Symbol* signature); | |||
| 291 | int size() { return _size; } | |||
| 292 | }; | |||
| 293 | ||||
| 294 | ||||
| 295 | class ArgumentCount: public SignatureIterator { | |||
| 296 | private: | |||
| 297 | int _size; | |||
| 298 | friend class SignatureIterator; // so do_parameters_on can call do_type | |||
| 299 | void do_type(BasicType type) { _size++; } | |||
| 300 | public: | |||
| 301 | ArgumentCount(Symbol* signature); | |||
| 302 | int size() { return _size; } | |||
| 303 | }; | |||
| 304 | ||||
| 305 | ||||
| 306 | class ReferenceArgumentCount: public SignatureIterator { | |||
| 307 | private: | |||
| 308 | int _refs; | |||
| 309 | friend class SignatureIterator; // so do_parameters_on can call do_type | |||
| 310 | void do_type(BasicType type) { if (is_reference_type(type)) _refs++; } | |||
| 311 | public: | |||
| 312 | ReferenceArgumentCount(Symbol* signature); | |||
| 313 | int count() { return _refs; } | |||
| 314 | }; | |||
| 315 | ||||
| 316 | ||||
| 317 | // Specialized SignatureIterator: Used to compute the result type. | |||
| 318 | ||||
| 319 | class ResultTypeFinder: public SignatureIterator { | |||
| 320 | public: | |||
| 321 | BasicType type() { return return_type(); } | |||
| 322 | ResultTypeFinder(Symbol* signature) : SignatureIterator(signature) { } | |||
| 323 | }; | |||
| 324 | ||||
| 325 | ||||
| 326 | // Fingerprinter computes a unique ID for a given method. The ID | |||
| 327 | // is a bitvector characterizing the methods signature (incl. the receiver). | |||
| 328 | class Fingerprinter: public SignatureIterator { | |||
| 329 | private: | |||
| 330 | fingerprint_t _accumulator; | |||
| 331 | int _param_size; | |||
| 332 | int _shift_count; | |||
| 333 | const Method* _method; | |||
| 334 | ||||
| 335 | void initialize_accumulator() { | |||
| 336 | _accumulator = 0; | |||
| 337 | _shift_count = fp_result_feature_size + fp_static_feature_size; | |||
| 338 | _param_size = 0; | |||
| 339 | } | |||
| 340 | ||||
| 341 | // Out-of-line method does it all in constructor: | |||
| 342 | void compute_fingerprint_and_return_type(bool static_flag = false); | |||
| 343 | ||||
| 344 | friend class SignatureIterator; // so do_parameters_on can call do_type | |||
| 345 | void do_type(BasicType type) { | |||
| 346 | assert(fp_is_valid_type(type), "bad parameter type")do { if (!(fp_is_valid_type(type))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.hpp" , 346, "assert(" "fp_is_valid_type(type)" ") failed", "bad parameter type" ); ::breakpoint(); } } while (0); | |||
| 347 | _accumulator |= ((fingerprint_t)type << _shift_count); | |||
| 348 | _shift_count += fp_parameter_feature_size; | |||
| 349 | _param_size += (is_double_word_type(type) ? 2 : 1); | |||
| 350 | } | |||
| 351 | ||||
| 352 | public: | |||
| 353 | int size_of_parameters() const { return _param_size; } | |||
| 354 | // fingerprint() and return_type() are in super class | |||
| 355 | ||||
| 356 | Fingerprinter(const methodHandle& method) | |||
| 357 | : SignatureIterator(method->signature()), | |||
| 358 | _method(method()) { | |||
| 359 | compute_fingerprint_and_return_type(); | |||
| 360 | } | |||
| 361 | Fingerprinter(Symbol* signature, bool is_static) | |||
| 362 | : SignatureIterator(signature), | |||
| 363 | _method(NULL__null) { | |||
| 364 | compute_fingerprint_and_return_type(is_static); | |||
| 365 | } | |||
| 366 | }; | |||
| 367 | ||||
| 368 | ||||
| 369 | // Specialized SignatureIterator: Used for native call purposes | |||
| 370 | ||||
| 371 | class NativeSignatureIterator: public SignatureIterator { | |||
| 372 | private: | |||
| 373 | methodHandle _method; | |||
| 374 | // We need separate JNI and Java offset values because in 64 bit mode, | |||
| 375 | // the argument offsets are not in sync with the Java stack. | |||
| 376 | // For example a long takes up 1 "C" stack entry but 2 Java stack entries. | |||
| 377 | int _offset; // The java stack offset | |||
| 378 | int _prepended; // number of prepended JNI parameters (1 JNIEnv, plus 1 mirror if static) | |||
| 379 | int _jni_offset; // the current parameter offset, starting with 0 | |||
| 380 | ||||
| 381 | friend class SignatureIterator; // so do_parameters_on can call do_type | |||
| 382 | void do_type(BasicType type) { | |||
| 383 | switch (type) { | |||
| 384 | case T_BYTE: | |||
| 385 | case T_BOOLEAN: | |||
| 386 | pass_byte(); _jni_offset++; _offset++; | |||
| 387 | break; | |||
| 388 | case T_CHAR: | |||
| 389 | case T_SHORT: | |||
| 390 | pass_short(); _jni_offset++; _offset++; | |||
| 391 | break; | |||
| 392 | case T_INT: | |||
| 393 | pass_int(); _jni_offset++; _offset++; | |||
| 394 | break; | |||
| 395 | case T_FLOAT: | |||
| 396 | pass_float(); _jni_offset++; _offset++; | |||
| 397 | break; | |||
| 398 | case T_DOUBLE: { | |||
| 399 | int jni_offset = LP64_ONLY(1)1 NOT_LP64(2); | |||
| 400 | pass_double(); _jni_offset += jni_offset; _offset += 2; | |||
| 401 | break; | |||
| 402 | } | |||
| 403 | case T_LONG: { | |||
| 404 | int jni_offset = LP64_ONLY(1)1 NOT_LP64(2); | |||
| 405 | pass_long(); _jni_offset += jni_offset; _offset += 2; | |||
| 406 | break; | |||
| 407 | } | |||
| 408 | case T_ARRAY: | |||
| 409 | case T_OBJECT: | |||
| 410 | pass_object(); _jni_offset++; _offset++; | |||
| 411 | break; | |||
| 412 | default: | |||
| 413 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.hpp" , 413); ::breakpoint(); } while (0); | |||
| 414 | } | |||
| 415 | } | |||
| 416 | ||||
| 417 | public: | |||
| 418 | methodHandle method() const { return _method; } | |||
| 419 | int offset() const { return _offset; } | |||
| 420 | int jni_offset() const { return _jni_offset + _prepended; } | |||
| 421 | bool is_static() const { return method()->is_static(); } | |||
| 422 | virtual void pass_int() = 0; | |||
| 423 | virtual void pass_long() = 0; | |||
| 424 | virtual void pass_object() = 0; // objects, arrays, inlines | |||
| 425 | virtual void pass_float() = 0; | |||
| 426 | virtual void pass_byte() { pass_int(); }; | |||
| 427 | virtual void pass_short() { pass_int(); }; | |||
| 428 | #ifdef _LP641 | |||
| 429 | virtual void pass_double() = 0; | |||
| 430 | #else | |||
| 431 | virtual void pass_double() { pass_long(); } // may be same as long | |||
| 432 | #endif | |||
| 433 | ||||
| 434 | NativeSignatureIterator(const methodHandle& method) : SignatureIterator(method->signature()) { | |||
| 435 | _method = method; | |||
| 436 | _offset = 0; | |||
| 437 | _jni_offset = 0; | |||
| 438 | ||||
| 439 | const int JNIEnv_words = 1; | |||
| 440 | const int mirror_words = 1; | |||
| 441 | _prepended = !is_static() ? JNIEnv_words : JNIEnv_words + mirror_words; | |||
| 442 | } | |||
| 443 | ||||
| 444 | void iterate() { iterate(Fingerprinter(method()).fingerprint()); } | |||
| 445 | ||||
| 446 | // iterate() calls the 3 virtual methods according to the following invocation syntax: | |||
| 447 | // | |||
| 448 | // {pass_int | pass_long | pass_object} | |||
| 449 | // | |||
| 450 | // Arguments are handled from left to right (receiver first, if any). | |||
| 451 | // The offset() values refer to the Java stack offsets but are 0 based and increasing. | |||
| 452 | // The java_offset() values count down to 0, and refer to the Java TOS. | |||
| 453 | // The jni_offset() values increase from 1 or 2, and refer to C arguments. | |||
| 454 | // The method's return type is ignored. | |||
| 455 | ||||
| 456 | void iterate(fingerprint_t fingerprint) { | |||
| 457 | set_fingerprint(fingerprint); | |||
| 458 | if (!is_static()) { | |||
| 459 | // handle receiver (not handled by iterate because not in signature) | |||
| 460 | pass_object(); _jni_offset++; _offset++; | |||
| 461 | } | |||
| 462 | do_parameters_on(this); | |||
| 463 | } | |||
| 464 | }; | |||
| 465 | ||||
| 466 | ||||
| 467 | // This is the core parsing logic for iterating over signatures. | |||
| 468 | // All of the previous classes use this for doing their work. | |||
| 469 | ||||
| 470 | class SignatureStream : public StackObj { | |||
| 471 | private: | |||
| 472 | const Symbol* _signature; | |||
| 473 | int _begin; | |||
| 474 | int _end; | |||
| 475 | int _limit; | |||
| 476 | int _array_prefix; // count of '[' before the array element descr | |||
| 477 | BasicType _type; | |||
| 478 | int _state; | |||
| 479 | Symbol* _previous_name; // cache the previously looked up symbol to avoid lookups | |||
| 480 | GrowableArray<Symbol*>* _names; // symbols created while parsing that need to be dereferenced | |||
| 481 | ||||
| 482 | Symbol* find_symbol(); | |||
| 483 | ||||
| 484 | enum { _s_field = 0, _s_method = 1, _s_method_return = 3 }; | |||
| 485 | void set_done() { | |||
| 486 | _state |= -2; // preserve s_method bit | |||
| 487 | assert(is_done(), "Unable to set state to done")do { if (!(is_done())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.hpp" , 487, "assert(" "is_done()" ") failed", "Unable to set state to done" ); ::breakpoint(); } } while (0); | |||
| 488 | } | |||
| 489 | int scan_type(BasicType bt); | |||
| 490 | ||||
| 491 | public: | |||
| 492 | bool at_return_type() const { return _state == (int)_s_method_return; } | |||
| 493 | bool is_done() const { return _state < 0; } | |||
| 494 | void next(); | |||
| 495 | ||||
| 496 | SignatureStream(const Symbol* signature, bool is_method = true); | |||
| 497 | ~SignatureStream(); | |||
| 498 | ||||
| 499 | bool is_reference() const { return is_reference_type(_type); } | |||
| 500 | bool is_array() const { return _type == T_ARRAY; } | |||
| 501 | bool is_primitive() const { return is_java_primitive(_type); } | |||
| 502 | BasicType type() const { return _type; } | |||
| ||||
| 503 | ||||
| 504 | const u1* raw_bytes() const { return _signature->bytes() + _begin; } | |||
| 505 | int raw_length() const { return _end - _begin; } | |||
| 506 | int raw_symbol_begin() const { return _begin + (has_envelope() ? 1 : 0); } | |||
| 507 | int raw_symbol_end() const { return _end - (has_envelope() ? 1 : 0); } | |||
| 508 | char raw_char_at(int i) const { | |||
| 509 | assert(i < _limit, "index for raw_char_at is over the limit")do { if (!(i < _limit)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.hpp" , 509, "assert(" "i < _limit" ") failed", "index for raw_char_at is over the limit" ); ::breakpoint(); } } while (0); | |||
| 510 | return _signature->char_at(i); | |||
| 511 | } | |||
| 512 | ||||
| 513 | // True if there is an embedded class name in this type, | |||
| 514 | // followed by ';'. | |||
| 515 | bool has_envelope() const { | |||
| 516 | if (!Signature::has_envelope(_signature->char_at(_begin))) | |||
| 517 | return false; | |||
| 518 | // this should always be true, but let's test it: | |||
| 519 | assert(_signature->char_at(_end-1) == JVM_SIGNATURE_ENDCLASS, "signature envelope has no semi-colon at end")do { if (!(_signature->char_at(_end-1) == JVM_SIGNATURE_ENDCLASS )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.hpp" , 519, "assert(" "_signature->char_at(_end-1) == JVM_SIGNATURE_ENDCLASS" ") failed", "signature envelope has no semi-colon at end"); :: breakpoint(); } } while (0); | |||
| 520 | return true; | |||
| 521 | } | |||
| 522 | ||||
| 523 | // return the symbol for chars in symbol_begin()..symbol_end() | |||
| 524 | Symbol* as_symbol() { | |||
| 525 | return find_symbol(); | |||
| 526 | } | |||
| 527 | ||||
| 528 | // in case you want only the return type: | |||
| 529 | void skip_to_return_type(); | |||
| 530 | ||||
| 531 | // number of '[' in array prefix | |||
| 532 | int array_prefix_length() { | |||
| 533 | return _type == T_ARRAY ? _array_prefix : 0; | |||
| 534 | } | |||
| 535 | ||||
| 536 | // In case you want only the array base type, | |||
| 537 | // reset the stream after skipping some brackets '['. | |||
| 538 | // (The argument is clipped to array_prefix_length(), | |||
| 539 | // and if it ends up as zero this call is a nop. | |||
| 540 | // The default is value skips all brackets '['.) | |||
| 541 | private: | |||
| 542 | int skip_whole_array_prefix(); | |||
| 543 | public: | |||
| 544 | int skip_array_prefix(int max_skip_length) { | |||
| 545 | if (_type != T_ARRAY) { | |||
| 546 | return 0; | |||
| 547 | } | |||
| 548 | if (_array_prefix > max_skip_length) { | |||
| 549 | // strip some but not all levels of T_ARRAY | |||
| 550 | _array_prefix -= max_skip_length; | |||
| 551 | _begin += max_skip_length; | |||
| 552 | return max_skip_length; | |||
| 553 | } | |||
| 554 | return skip_whole_array_prefix(); | |||
| 555 | } | |||
| 556 | int skip_array_prefix() { | |||
| 557 | if (_type != T_ARRAY) { | |||
| 558 | return 0; | |||
| 559 | } | |||
| 560 | return skip_whole_array_prefix(); | |||
| 561 | } | |||
| 562 | ||||
| 563 | // free-standing lookups (bring your own CL/PD pair) | |||
| 564 | enum FailureMode { ReturnNull, NCDFError, CachedOrNull }; | |||
| 565 | Klass* as_klass(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPSJavaThread* __the_thread__); | |||
| 566 | oop as_java_mirror(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPSJavaThread* __the_thread__); | |||
| 567 | }; | |||
| 568 | ||||
| 569 | // Specialized SignatureStream: used for invoking SystemDictionary to either find | |||
| 570 | // or resolve the underlying type when iterating over a | |||
| 571 | // Java descriptor (or parts of it). | |||
| 572 | class ResolvingSignatureStream : public SignatureStream { | |||
| 573 | Klass* _load_origin; | |||
| 574 | bool _handles_cached; | |||
| 575 | Handle _class_loader; // cached when needed | |||
| 576 | Handle _protection_domain; // cached when needed | |||
| 577 | ||||
| 578 | void initialize_load_origin(Klass* load_origin) { | |||
| 579 | _load_origin = load_origin; | |||
| 580 | _handles_cached = (load_origin == NULL__null); | |||
| 581 | } | |||
| 582 | void need_handles() { | |||
| 583 | if (!_handles_cached) { | |||
| 584 | cache_handles(); | |||
| 585 | _handles_cached = true; | |||
| 586 | } | |||
| 587 | } | |||
| 588 | void cache_handles(); | |||
| 589 | ||||
| 590 | public: | |||
| 591 | ResolvingSignatureStream(Symbol* signature, Klass* load_origin, bool is_method = true); | |||
| 592 | ResolvingSignatureStream(Symbol* signature, Handle class_loader, Handle protection_domain, bool is_method = true); | |||
| 593 | ResolvingSignatureStream(const Method* method); | |||
| 594 | ResolvingSignatureStream(fieldDescriptor& field); | |||
| 595 | ||||
| 596 | Klass* load_origin() { return _load_origin; } | |||
| 597 | Handle class_loader() { need_handles(); return _class_loader; } | |||
| 598 | Handle protection_domain() { need_handles(); return _protection_domain; } | |||
| 599 | ||||
| 600 | Klass* as_klass_if_loaded(TRAPSJavaThread* __the_thread__); | |||
| 601 | Klass* as_klass(FailureMode failure_mode, TRAPSJavaThread* __the_thread__) { | |||
| 602 | need_handles(); | |||
| 603 | return SignatureStream::as_klass(_class_loader, _protection_domain, | |||
| 604 | failure_mode, THREAD__the_thread__); | |||
| 605 | } | |||
| 606 | oop as_java_mirror(FailureMode failure_mode, TRAPSJavaThread* __the_thread__) { | |||
| 607 | if (is_reference()) { | |||
| 608 | need_handles(); | |||
| 609 | } | |||
| 610 | return SignatureStream::as_java_mirror(_class_loader, _protection_domain, | |||
| 611 | failure_mode, THREAD__the_thread__); | |||
| 612 | } | |||
| 613 | }; | |||
| 614 | ||||
| 615 | // Here is how all the SignatureIterator classes invoke the | |||
| 616 | // SignatureStream engine to do their parsing. | |||
| 617 | template<typename T> inline | |||
| 618 | void SignatureIterator::do_parameters_on(T* callback) { | |||
| 619 | fingerprint_t unaccumulator = _fingerprint; | |||
| 620 | ||||
| 621 | // Check for too many arguments, or missing fingerprint: | |||
| 622 | if (!fp_is_valid(unaccumulator)) { | |||
| 623 | SignatureStream ss(_signature); | |||
| 624 | for (; !ss.at_return_type(); ss.next()) { | |||
| 625 | callback->do_type(ss.type()); | |||
| 626 | } | |||
| 627 | // while we are here, capture the return type | |||
| 628 | _return_type = ss.type(); | |||
| 629 | } else { | |||
| 630 | // Optimized version of do_parameters when fingerprint is known | |||
| 631 | assert(_return_type != T_ILLEGAL, "return type already captured from fp")do { if (!(_return_type != T_ILLEGAL)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.hpp" , 631, "assert(" "_return_type != T_ILLEGAL" ") failed", "return type already captured from fp" ); ::breakpoint(); } } while (0); | |||
| 632 | unaccumulator = fp_start_parameters(unaccumulator); | |||
| 633 | for (BasicType type; (type = fp_next_parameter(unaccumulator)) != (BasicType)fp_parameters_done; ) { | |||
| 634 | assert(fp_is_valid_type(type), "garbled fingerprint")do { if (!(fp_is_valid_type(type))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/runtime/signature.hpp" , 634, "assert(" "fp_is_valid_type(type)" ") failed", "garbled fingerprint" ); ::breakpoint(); } } while (0); | |||
| 635 | callback->do_type(type); | |||
| 636 | } | |||
| 637 | } | |||
| 638 | } | |||
| 639 | ||||
| 640 | #ifdef ASSERT1 | |||
| 641 | class SignatureVerifier : public StackObj { | |||
| 642 | public: | |||
| 643 | static bool is_valid_method_signature(Symbol* sig); | |||
| 644 | static bool is_valid_type_signature(Symbol* sig); | |||
| 645 | private: | |||
| 646 | static ssize_t is_valid_type(const char*, ssize_t); | |||
| 647 | }; | |||
| 648 | #endif | |||
| 649 | #endif // SHARE_RUNTIME_SIGNATURE_HPP |