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 |