File: | jdk/src/hotspot/share/oops/constMethod.hpp |
Warning: | line 449, column 7 Null pointer passed to 2nd parameter expecting 'nonnull' |
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 | #include "precompiled.hpp" | ||||||||||||
25 | #include "jvm.h" | ||||||||||||
26 | #include "classfile/classFileParser.hpp" | ||||||||||||
27 | #include "classfile/classFileStream.hpp" | ||||||||||||
28 | #include "classfile/classLoader.hpp" | ||||||||||||
29 | #include "classfile/classLoaderData.inline.hpp" | ||||||||||||
30 | #include "classfile/classLoadInfo.hpp" | ||||||||||||
31 | #include "classfile/defaultMethods.hpp" | ||||||||||||
32 | #include "classfile/fieldLayoutBuilder.hpp" | ||||||||||||
33 | #include "classfile/javaClasses.inline.hpp" | ||||||||||||
34 | #include "classfile/moduleEntry.hpp" | ||||||||||||
35 | #include "classfile/packageEntry.hpp" | ||||||||||||
36 | #include "classfile/symbolTable.hpp" | ||||||||||||
37 | #include "classfile/systemDictionary.hpp" | ||||||||||||
38 | #include "classfile/verificationType.hpp" | ||||||||||||
39 | #include "classfile/verifier.hpp" | ||||||||||||
40 | #include "classfile/vmClasses.hpp" | ||||||||||||
41 | #include "classfile/vmSymbols.hpp" | ||||||||||||
42 | #include "logging/log.hpp" | ||||||||||||
43 | #include "logging/logStream.hpp" | ||||||||||||
44 | #include "memory/allocation.hpp" | ||||||||||||
45 | #include "memory/metadataFactory.hpp" | ||||||||||||
46 | #include "memory/oopFactory.hpp" | ||||||||||||
47 | #include "memory/resourceArea.hpp" | ||||||||||||
48 | #include "memory/universe.hpp" | ||||||||||||
49 | #include "oops/annotations.hpp" | ||||||||||||
50 | #include "oops/constantPool.inline.hpp" | ||||||||||||
51 | #include "oops/fieldStreams.inline.hpp" | ||||||||||||
52 | #include "oops/instanceKlass.inline.hpp" | ||||||||||||
53 | #include "oops/instanceMirrorKlass.hpp" | ||||||||||||
54 | #include "oops/klass.inline.hpp" | ||||||||||||
55 | #include "oops/klassVtable.hpp" | ||||||||||||
56 | #include "oops/metadata.hpp" | ||||||||||||
57 | #include "oops/method.inline.hpp" | ||||||||||||
58 | #include "oops/oop.inline.hpp" | ||||||||||||
59 | #include "oops/recordComponent.hpp" | ||||||||||||
60 | #include "oops/symbol.hpp" | ||||||||||||
61 | #include "prims/jvmtiExport.hpp" | ||||||||||||
62 | #include "prims/jvmtiThreadState.hpp" | ||||||||||||
63 | #include "runtime/arguments.hpp" | ||||||||||||
64 | #include "runtime/fieldDescriptor.inline.hpp" | ||||||||||||
65 | #include "runtime/handles.inline.hpp" | ||||||||||||
66 | #include "runtime/javaCalls.hpp" | ||||||||||||
67 | #include "runtime/os.hpp" | ||||||||||||
68 | #include "runtime/perfData.hpp" | ||||||||||||
69 | #include "runtime/reflection.hpp" | ||||||||||||
70 | #include "runtime/safepointVerifiers.hpp" | ||||||||||||
71 | #include "runtime/signature.hpp" | ||||||||||||
72 | #include "runtime/timer.hpp" | ||||||||||||
73 | #include "services/classLoadingService.hpp" | ||||||||||||
74 | #include "services/threadService.hpp" | ||||||||||||
75 | #include "utilities/align.hpp" | ||||||||||||
76 | #include "utilities/bitMap.inline.hpp" | ||||||||||||
77 | #include "utilities/copy.hpp" | ||||||||||||
78 | #include "utilities/formatBuffer.hpp" | ||||||||||||
79 | #include "utilities/exceptions.hpp" | ||||||||||||
80 | #include "utilities/globalDefinitions.hpp" | ||||||||||||
81 | #include "utilities/growableArray.hpp" | ||||||||||||
82 | #include "utilities/macros.hpp" | ||||||||||||
83 | #include "utilities/ostream.hpp" | ||||||||||||
84 | #include "utilities/resourceHash.hpp" | ||||||||||||
85 | #include "utilities/utf8.hpp" | ||||||||||||
86 | |||||||||||||
87 | #if INCLUDE_CDS1 | ||||||||||||
88 | #include "classfile/systemDictionaryShared.hpp" | ||||||||||||
89 | #endif | ||||||||||||
90 | #if INCLUDE_JFR1 | ||||||||||||
91 | #include "jfr/support/jfrTraceIdExtension.hpp" | ||||||||||||
92 | #endif | ||||||||||||
93 | |||||||||||||
94 | // We generally try to create the oops directly when parsing, rather than | ||||||||||||
95 | // allocating temporary data structures and copying the bytes twice. A | ||||||||||||
96 | // temporary area is only needed when parsing utf8 entries in the constant | ||||||||||||
97 | // pool and when parsing line number tables. | ||||||||||||
98 | |||||||||||||
99 | // We add assert in debug mode when class format is not checked. | ||||||||||||
100 | |||||||||||||
101 | #define JAVA_CLASSFILE_MAGIC0xCAFEBABE 0xCAFEBABE | ||||||||||||
102 | #define JAVA_MIN_SUPPORTED_VERSION45 45 | ||||||||||||
103 | #define JAVA_PREVIEW_MINOR_VERSION65535 65535 | ||||||||||||
104 | |||||||||||||
105 | // Used for two backward compatibility reasons: | ||||||||||||
106 | // - to check for new additions to the class file format in JDK1.5 | ||||||||||||
107 | // - to check for bug fixes in the format checker in JDK1.5 | ||||||||||||
108 | #define JAVA_1_5_VERSION49 49 | ||||||||||||
109 | |||||||||||||
110 | // Used for backward compatibility reasons: | ||||||||||||
111 | // - to check for javac bug fixes that happened after 1.5 | ||||||||||||
112 | // - also used as the max version when running in jdk6 | ||||||||||||
113 | #define JAVA_6_VERSION50 50 | ||||||||||||
114 | |||||||||||||
115 | // Used for backward compatibility reasons: | ||||||||||||
116 | // - to disallow argument and require ACC_STATIC for <clinit> methods | ||||||||||||
117 | #define JAVA_7_VERSION51 51 | ||||||||||||
118 | |||||||||||||
119 | // Extension method support. | ||||||||||||
120 | #define JAVA_8_VERSION52 52 | ||||||||||||
121 | |||||||||||||
122 | #define JAVA_9_VERSION53 53 | ||||||||||||
123 | |||||||||||||
124 | #define JAVA_10_VERSION54 54 | ||||||||||||
125 | |||||||||||||
126 | #define JAVA_11_VERSION55 55 | ||||||||||||
127 | |||||||||||||
128 | #define JAVA_12_VERSION56 56 | ||||||||||||
129 | |||||||||||||
130 | #define JAVA_13_VERSION57 57 | ||||||||||||
131 | |||||||||||||
132 | #define JAVA_14_VERSION58 58 | ||||||||||||
133 | |||||||||||||
134 | #define JAVA_15_VERSION59 59 | ||||||||||||
135 | |||||||||||||
136 | #define JAVA_16_VERSION60 60 | ||||||||||||
137 | |||||||||||||
138 | #define JAVA_17_VERSION61 61 | ||||||||||||
139 | |||||||||||||
140 | #define JAVA_18_VERSION62 62 | ||||||||||||
141 | |||||||||||||
142 | #define JAVA_19_VERSION63 63 | ||||||||||||
143 | |||||||||||||
144 | void ClassFileParser::set_class_bad_constant_seen(short bad_constant) { | ||||||||||||
145 | assert((bad_constant == JVM_CONSTANT_Module ||do { if (!((bad_constant == JVM_CONSTANT_Module || bad_constant == JVM_CONSTANT_Package) && _major_version >= 53) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 147, "assert(" "(bad_constant == JVM_CONSTANT_Module || bad_constant == JVM_CONSTANT_Package) && _major_version >= 53" ") failed", "Unexpected bad constant pool entry"); ::breakpoint (); } } while (0) | ||||||||||||
146 | bad_constant == JVM_CONSTANT_Package) && _major_version >= JAVA_9_VERSION,do { if (!((bad_constant == JVM_CONSTANT_Module || bad_constant == JVM_CONSTANT_Package) && _major_version >= 53) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 147, "assert(" "(bad_constant == JVM_CONSTANT_Module || bad_constant == JVM_CONSTANT_Package) && _major_version >= 53" ") failed", "Unexpected bad constant pool entry"); ::breakpoint (); } } while (0) | ||||||||||||
147 | "Unexpected bad constant pool entry")do { if (!((bad_constant == JVM_CONSTANT_Module || bad_constant == JVM_CONSTANT_Package) && _major_version >= 53) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 147, "assert(" "(bad_constant == JVM_CONSTANT_Module || bad_constant == JVM_CONSTANT_Package) && _major_version >= 53" ") failed", "Unexpected bad constant pool entry"); ::breakpoint (); } } while (0); | ||||||||||||
148 | if (_bad_constant_seen == 0) _bad_constant_seen = bad_constant; | ||||||||||||
149 | } | ||||||||||||
150 | |||||||||||||
151 | void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const stream, | ||||||||||||
152 | ConstantPool* cp, | ||||||||||||
153 | const int length, | ||||||||||||
154 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
155 | assert(stream != NULL, "invariant")do { if (!(stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 155, "assert(" "stream != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
156 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 156, "assert(" "cp != __null" ") failed", "invariant"); ::breakpoint (); } } while (0); | ||||||||||||
157 | |||||||||||||
158 | // Use a local copy of ClassFileStream. It helps the C++ compiler to optimize | ||||||||||||
159 | // this function (_current can be allocated in a register, with scalar | ||||||||||||
160 | // replacement of aggregates). The _current pointer is copied back to | ||||||||||||
161 | // stream() when this function returns. DON'T call another method within | ||||||||||||
162 | // this method that uses stream(). | ||||||||||||
163 | const ClassFileStream cfs1 = *stream; | ||||||||||||
164 | const ClassFileStream* const cfs = &cfs1; | ||||||||||||
165 | |||||||||||||
166 | assert(cfs->allocated_on_stack_or_embedded(), "should be local")do { if (!(cfs->allocated_on_stack_or_embedded())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 166, "assert(" "cfs->allocated_on_stack_or_embedded()" ") failed" , "should be local"); ::breakpoint(); } } while (0); | ||||||||||||
167 | debug_only(const u1* const old_current = stream->current();)const u1* const old_current = stream->current(); | ||||||||||||
168 | |||||||||||||
169 | // Used for batching symbol allocations. | ||||||||||||
170 | const char* names[SymbolTable::symbol_alloc_batch_size]; | ||||||||||||
171 | int lengths[SymbolTable::symbol_alloc_batch_size]; | ||||||||||||
172 | int indices[SymbolTable::symbol_alloc_batch_size]; | ||||||||||||
173 | unsigned int hashValues[SymbolTable::symbol_alloc_batch_size]; | ||||||||||||
174 | int names_count = 0; | ||||||||||||
175 | |||||||||||||
176 | // parsing Index 0 is unused | ||||||||||||
177 | for (int index = 1; index < length; index++) { | ||||||||||||
178 | // Each of the following case guarantees one more byte in the stream | ||||||||||||
179 | // for the following tag or the access_flags following constant pool, | ||||||||||||
180 | // so we don't need bounds-check for reading tag. | ||||||||||||
181 | const u1 tag = cfs->get_u1_fast(); | ||||||||||||
182 | switch (tag) { | ||||||||||||
183 | case JVM_CONSTANT_Class : { | ||||||||||||
184 | cfs->guarantee_more(3, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // name_index, tag/access_flags | ||||||||||||
185 | const u2 name_index = cfs->get_u2_fast(); | ||||||||||||
186 | cp->klass_index_at_put(index, name_index); | ||||||||||||
187 | break; | ||||||||||||
188 | } | ||||||||||||
189 | case JVM_CONSTANT_Fieldref: { | ||||||||||||
190 | cfs->guarantee_more(5, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // class_index, name_and_type_index, tag/access_flags | ||||||||||||
191 | const u2 class_index = cfs->get_u2_fast(); | ||||||||||||
192 | const u2 name_and_type_index = cfs->get_u2_fast(); | ||||||||||||
193 | cp->field_at_put(index, class_index, name_and_type_index); | ||||||||||||
194 | break; | ||||||||||||
195 | } | ||||||||||||
196 | case JVM_CONSTANT_Methodref: { | ||||||||||||
197 | cfs->guarantee_more(5, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // class_index, name_and_type_index, tag/access_flags | ||||||||||||
198 | const u2 class_index = cfs->get_u2_fast(); | ||||||||||||
199 | const u2 name_and_type_index = cfs->get_u2_fast(); | ||||||||||||
200 | cp->method_at_put(index, class_index, name_and_type_index); | ||||||||||||
201 | break; | ||||||||||||
202 | } | ||||||||||||
203 | case JVM_CONSTANT_InterfaceMethodref: { | ||||||||||||
204 | cfs->guarantee_more(5, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // class_index, name_and_type_index, tag/access_flags | ||||||||||||
205 | const u2 class_index = cfs->get_u2_fast(); | ||||||||||||
206 | const u2 name_and_type_index = cfs->get_u2_fast(); | ||||||||||||
207 | cp->interface_method_at_put(index, class_index, name_and_type_index); | ||||||||||||
208 | break; | ||||||||||||
209 | } | ||||||||||||
210 | case JVM_CONSTANT_String : { | ||||||||||||
211 | cfs->guarantee_more(3, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // string_index, tag/access_flags | ||||||||||||
212 | const u2 string_index = cfs->get_u2_fast(); | ||||||||||||
213 | cp->string_index_at_put(index, string_index); | ||||||||||||
214 | break; | ||||||||||||
215 | } | ||||||||||||
216 | case JVM_CONSTANT_MethodHandle : | ||||||||||||
217 | case JVM_CONSTANT_MethodType: { | ||||||||||||
218 | if (_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { | ||||||||||||
219 | classfile_parse_error( | ||||||||||||
220 | "Class file version does not support constant tag %u in class file %s", | ||||||||||||
221 | tag, THREAD__the_thread__); | ||||||||||||
222 | return; | ||||||||||||
223 | } | ||||||||||||
224 | if (tag == JVM_CONSTANT_MethodHandle) { | ||||||||||||
225 | cfs->guarantee_more(4, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // ref_kind, method_index, tag/access_flags | ||||||||||||
226 | const u1 ref_kind = cfs->get_u1_fast(); | ||||||||||||
227 | const u2 method_index = cfs->get_u2_fast(); | ||||||||||||
228 | cp->method_handle_index_at_put(index, ref_kind, method_index); | ||||||||||||
229 | } | ||||||||||||
230 | else if (tag == JVM_CONSTANT_MethodType) { | ||||||||||||
231 | cfs->guarantee_more(3, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // signature_index, tag/access_flags | ||||||||||||
232 | const u2 signature_index = cfs->get_u2_fast(); | ||||||||||||
233 | cp->method_type_index_at_put(index, signature_index); | ||||||||||||
234 | } | ||||||||||||
235 | else { | ||||||||||||
236 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 236); ::breakpoint(); } while (0); | ||||||||||||
237 | } | ||||||||||||
238 | break; | ||||||||||||
239 | } | ||||||||||||
240 | case JVM_CONSTANT_Dynamic : { | ||||||||||||
241 | if (_major_version < Verifier::DYNAMICCONSTANT_MAJOR_VERSION) { | ||||||||||||
242 | classfile_parse_error( | ||||||||||||
243 | "Class file version does not support constant tag %u in class file %s", | ||||||||||||
244 | tag, THREAD__the_thread__); | ||||||||||||
245 | return; | ||||||||||||
246 | } | ||||||||||||
247 | cfs->guarantee_more(5, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // bsm_index, nt, tag/access_flags | ||||||||||||
248 | const u2 bootstrap_specifier_index = cfs->get_u2_fast(); | ||||||||||||
249 | const u2 name_and_type_index = cfs->get_u2_fast(); | ||||||||||||
250 | if (_max_bootstrap_specifier_index < (int) bootstrap_specifier_index) { | ||||||||||||
251 | _max_bootstrap_specifier_index = (int) bootstrap_specifier_index; // collect for later | ||||||||||||
252 | } | ||||||||||||
253 | cp->dynamic_constant_at_put(index, bootstrap_specifier_index, name_and_type_index); | ||||||||||||
254 | break; | ||||||||||||
255 | } | ||||||||||||
256 | case JVM_CONSTANT_InvokeDynamic : { | ||||||||||||
257 | if (_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { | ||||||||||||
258 | classfile_parse_error( | ||||||||||||
259 | "Class file version does not support constant tag %u in class file %s", | ||||||||||||
260 | tag, THREAD__the_thread__); | ||||||||||||
261 | return; | ||||||||||||
262 | } | ||||||||||||
263 | cfs->guarantee_more(5, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // bsm_index, nt, tag/access_flags | ||||||||||||
264 | const u2 bootstrap_specifier_index = cfs->get_u2_fast(); | ||||||||||||
265 | const u2 name_and_type_index = cfs->get_u2_fast(); | ||||||||||||
266 | if (_max_bootstrap_specifier_index < (int) bootstrap_specifier_index) { | ||||||||||||
267 | _max_bootstrap_specifier_index = (int) bootstrap_specifier_index; // collect for later | ||||||||||||
268 | } | ||||||||||||
269 | cp->invoke_dynamic_at_put(index, bootstrap_specifier_index, name_and_type_index); | ||||||||||||
270 | break; | ||||||||||||
271 | } | ||||||||||||
272 | case JVM_CONSTANT_Integer: { | ||||||||||||
273 | cfs->guarantee_more(5, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // bytes, tag/access_flags | ||||||||||||
274 | const u4 bytes = cfs->get_u4_fast(); | ||||||||||||
275 | cp->int_at_put(index, (jint)bytes); | ||||||||||||
276 | break; | ||||||||||||
277 | } | ||||||||||||
278 | case JVM_CONSTANT_Float: { | ||||||||||||
279 | cfs->guarantee_more(5, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // bytes, tag/access_flags | ||||||||||||
280 | const u4 bytes = cfs->get_u4_fast(); | ||||||||||||
281 | cp->float_at_put(index, *(jfloat*)&bytes); | ||||||||||||
282 | break; | ||||||||||||
283 | } | ||||||||||||
284 | case JVM_CONSTANT_Long: { | ||||||||||||
285 | // A mangled type might cause you to overrun allocated memory | ||||||||||||
286 | guarantee_property(index + 1 < length, | ||||||||||||
287 | "Invalid constant pool entry %u in class file %s", | ||||||||||||
288 | index, | ||||||||||||
289 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
290 | cfs->guarantee_more(9, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // bytes, tag/access_flags | ||||||||||||
291 | const u8 bytes = cfs->get_u8_fast(); | ||||||||||||
292 | cp->long_at_put(index, bytes); | ||||||||||||
293 | index++; // Skip entry following eigth-byte constant, see JVM book p. 98 | ||||||||||||
294 | break; | ||||||||||||
295 | } | ||||||||||||
296 | case JVM_CONSTANT_Double: { | ||||||||||||
297 | // A mangled type might cause you to overrun allocated memory | ||||||||||||
298 | guarantee_property(index+1 < length, | ||||||||||||
299 | "Invalid constant pool entry %u in class file %s", | ||||||||||||
300 | index, | ||||||||||||
301 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
302 | cfs->guarantee_more(9, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // bytes, tag/access_flags | ||||||||||||
303 | const u8 bytes = cfs->get_u8_fast(); | ||||||||||||
304 | cp->double_at_put(index, *(jdouble*)&bytes); | ||||||||||||
305 | index++; // Skip entry following eigth-byte constant, see JVM book p. 98 | ||||||||||||
306 | break; | ||||||||||||
307 | } | ||||||||||||
308 | case JVM_CONSTANT_NameAndType: { | ||||||||||||
309 | cfs->guarantee_more(5, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // name_index, signature_index, tag/access_flags | ||||||||||||
310 | const u2 name_index = cfs->get_u2_fast(); | ||||||||||||
311 | const u2 signature_index = cfs->get_u2_fast(); | ||||||||||||
312 | cp->name_and_type_at_put(index, name_index, signature_index); | ||||||||||||
313 | break; | ||||||||||||
314 | } | ||||||||||||
315 | case JVM_CONSTANT_Utf8 : { | ||||||||||||
316 | cfs->guarantee_more(2, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // utf8_length | ||||||||||||
317 | u2 utf8_length = cfs->get_u2_fast(); | ||||||||||||
318 | const u1* utf8_buffer = cfs->current(); | ||||||||||||
319 | assert(utf8_buffer != NULL, "null utf8 buffer")do { if (!(utf8_buffer != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 319, "assert(" "utf8_buffer != __null" ") failed", "null utf8 buffer" ); ::breakpoint(); } } while (0); | ||||||||||||
320 | // Got utf8 string, guarantee utf8_length+1 bytes, set stream position forward. | ||||||||||||
321 | cfs->guarantee_more(utf8_length+1, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // utf8 string, tag/access_flags | ||||||||||||
322 | cfs->skip_u1_fast(utf8_length); | ||||||||||||
323 | |||||||||||||
324 | // Before storing the symbol, make sure it's legal | ||||||||||||
325 | if (_need_verify) { | ||||||||||||
326 | verify_legal_utf8(utf8_buffer, utf8_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
327 | } | ||||||||||||
328 | |||||||||||||
329 | unsigned int hash; | ||||||||||||
330 | Symbol* const result = SymbolTable::lookup_only((const char*)utf8_buffer, | ||||||||||||
331 | utf8_length, | ||||||||||||
332 | hash); | ||||||||||||
333 | if (result == NULL__null) { | ||||||||||||
334 | names[names_count] = (const char*)utf8_buffer; | ||||||||||||
335 | lengths[names_count] = utf8_length; | ||||||||||||
336 | indices[names_count] = index; | ||||||||||||
337 | hashValues[names_count++] = hash; | ||||||||||||
338 | if (names_count == SymbolTable::symbol_alloc_batch_size) { | ||||||||||||
339 | SymbolTable::new_symbols(_loader_data, | ||||||||||||
340 | constantPoolHandle(THREAD__the_thread__, cp), | ||||||||||||
341 | names_count, | ||||||||||||
342 | names, | ||||||||||||
343 | lengths, | ||||||||||||
344 | indices, | ||||||||||||
345 | hashValues); | ||||||||||||
346 | names_count = 0; | ||||||||||||
347 | } | ||||||||||||
348 | } else { | ||||||||||||
349 | cp->symbol_at_put(index, result); | ||||||||||||
350 | } | ||||||||||||
351 | break; | ||||||||||||
352 | } | ||||||||||||
353 | case JVM_CONSTANT_Module: | ||||||||||||
354 | case JVM_CONSTANT_Package: { | ||||||||||||
355 | // Record that an error occurred in these two cases but keep parsing so | ||||||||||||
356 | // that ACC_Module can be checked for in the access_flags. Need to | ||||||||||||
357 | // throw NoClassDefFoundError in that case. | ||||||||||||
358 | if (_major_version >= JAVA_9_VERSION53) { | ||||||||||||
359 | cfs->guarantee_more(3, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
360 | cfs->get_u2_fast(); | ||||||||||||
361 | set_class_bad_constant_seen(tag); | ||||||||||||
362 | break; | ||||||||||||
363 | } | ||||||||||||
364 | } | ||||||||||||
365 | default: { | ||||||||||||
366 | classfile_parse_error("Unknown constant tag %u in class file %s", | ||||||||||||
367 | tag, | ||||||||||||
368 | THREAD__the_thread__); | ||||||||||||
369 | return; | ||||||||||||
370 | } | ||||||||||||
371 | } // end of switch(tag) | ||||||||||||
372 | } // end of for | ||||||||||||
373 | |||||||||||||
374 | // Allocate the remaining symbols | ||||||||||||
375 | if (names_count > 0) { | ||||||||||||
376 | SymbolTable::new_symbols(_loader_data, | ||||||||||||
377 | constantPoolHandle(THREAD__the_thread__, cp), | ||||||||||||
378 | names_count, | ||||||||||||
379 | names, | ||||||||||||
380 | lengths, | ||||||||||||
381 | indices, | ||||||||||||
382 | hashValues); | ||||||||||||
383 | } | ||||||||||||
384 | |||||||||||||
385 | // Copy _current pointer of local copy back to stream. | ||||||||||||
386 | assert(stream->current() == old_current, "non-exclusive use of stream")do { if (!(stream->current() == old_current)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 386, "assert(" "stream->current() == old_current" ") failed" , "non-exclusive use of stream"); ::breakpoint(); } } while ( 0); | ||||||||||||
387 | stream->set_current(cfs1.current()); | ||||||||||||
388 | |||||||||||||
389 | } | ||||||||||||
390 | |||||||||||||
391 | static inline bool valid_cp_range(int index, int length) { | ||||||||||||
392 | return (index > 0 && index < length); | ||||||||||||
393 | } | ||||||||||||
394 | |||||||||||||
395 | static inline Symbol* check_symbol_at(const ConstantPool* cp, int index) { | ||||||||||||
396 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 396, "assert(" "cp != __null" ") failed", "invariant"); ::breakpoint (); } } while (0); | ||||||||||||
397 | if (valid_cp_range(index, cp->length()) && cp->tag_at(index).is_utf8()) { | ||||||||||||
398 | return cp->symbol_at(index); | ||||||||||||
399 | } | ||||||||||||
400 | return NULL__null; | ||||||||||||
401 | } | ||||||||||||
402 | |||||||||||||
403 | #ifdef ASSERT1 | ||||||||||||
404 | PRAGMA_DIAG_PUSHGCC diagnostic push | ||||||||||||
405 | PRAGMA_FORMAT_NONLITERAL_IGNOREDGCC diagnostic ignored "-Wformat-nonliteral"
GCC diagnostic ignored "-Wformat-security" | ||||||||||||
406 | void ClassFileParser::report_assert_property_failure(const char* msg, TRAPSJavaThread* __the_thread__) const { | ||||||||||||
407 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
408 | fatal(msg, _class_name->as_C_string())do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 408, msg, _class_name->as_C_string()); ::breakpoint(); } while (0); | ||||||||||||
409 | } | ||||||||||||
410 | |||||||||||||
411 | void ClassFileParser::report_assert_property_failure(const char* msg, | ||||||||||||
412 | int index, | ||||||||||||
413 | TRAPSJavaThread* __the_thread__) const { | ||||||||||||
414 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
415 | fatal(msg, index, _class_name->as_C_string())do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 415, msg, index, _class_name->as_C_string()); ::breakpoint (); } while (0); | ||||||||||||
416 | } | ||||||||||||
417 | PRAGMA_DIAG_POPGCC diagnostic pop | ||||||||||||
418 | #endif | ||||||||||||
419 | |||||||||||||
420 | void ClassFileParser::parse_constant_pool(const ClassFileStream* const stream, | ||||||||||||
421 | ConstantPool* const cp, | ||||||||||||
422 | const int length, | ||||||||||||
423 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
424 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 424, "assert(" "cp != __null" ") failed", "invariant"); ::breakpoint (); } } while (0); | ||||||||||||
425 | assert(stream != NULL, "invariant")do { if (!(stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 425, "assert(" "stream != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
426 | |||||||||||||
427 | // parsing constant pool entries | ||||||||||||
428 | parse_constant_pool_entries(stream, cp, length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
429 | if (class_bad_constant_seen() != 0) { | ||||||||||||
430 | // a bad CP entry has been detected previously so stop parsing and just return. | ||||||||||||
431 | return; | ||||||||||||
432 | } | ||||||||||||
433 | |||||||||||||
434 | int index = 1; // declared outside of loops for portability | ||||||||||||
435 | int num_klasses = 0; | ||||||||||||
436 | |||||||||||||
437 | // first verification pass - validate cross references | ||||||||||||
438 | // and fixup class and string constants | ||||||||||||
439 | for (index = 1; index < length; index++) { // Index 0 is unused | ||||||||||||
440 | const jbyte tag = cp->tag_at(index).value(); | ||||||||||||
441 | switch (tag) { | ||||||||||||
442 | case JVM_CONSTANT_Class: { | ||||||||||||
443 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 443); ::breakpoint(); } while (0); // Only JVM_CONSTANT_ClassIndex should be present | ||||||||||||
444 | break; | ||||||||||||
445 | } | ||||||||||||
446 | case JVM_CONSTANT_Fieldref: | ||||||||||||
447 | // fall through | ||||||||||||
448 | case JVM_CONSTANT_Methodref: | ||||||||||||
449 | // fall through | ||||||||||||
450 | case JVM_CONSTANT_InterfaceMethodref: { | ||||||||||||
451 | if (!_need_verify) break; | ||||||||||||
452 | const int klass_ref_index = cp->klass_ref_index_at(index); | ||||||||||||
453 | const int name_and_type_ref_index = cp->name_and_type_ref_index_at(index); | ||||||||||||
454 | check_property(valid_klass_reference_at(klass_ref_index), | ||||||||||||
455 | "Invalid constant pool index %u in class file %s", | ||||||||||||
456 | klass_ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
457 | check_property(valid_cp_range(name_and_type_ref_index, length) && | ||||||||||||
458 | cp->tag_at(name_and_type_ref_index).is_name_and_type(), | ||||||||||||
459 | "Invalid constant pool index %u in class file %s", | ||||||||||||
460 | name_and_type_ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
461 | break; | ||||||||||||
462 | } | ||||||||||||
463 | case JVM_CONSTANT_String: { | ||||||||||||
464 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 464); ::breakpoint(); } while (0); // Only JVM_CONSTANT_StringIndex should be present | ||||||||||||
465 | break; | ||||||||||||
466 | } | ||||||||||||
467 | case JVM_CONSTANT_Integer: | ||||||||||||
468 | break; | ||||||||||||
469 | case JVM_CONSTANT_Float: | ||||||||||||
470 | break; | ||||||||||||
471 | case JVM_CONSTANT_Long: | ||||||||||||
472 | case JVM_CONSTANT_Double: { | ||||||||||||
473 | index++; | ||||||||||||
474 | check_property( | ||||||||||||
475 | (index < length && cp->tag_at(index).is_invalid()), | ||||||||||||
476 | "Improper constant pool long/double index %u in class file %s", | ||||||||||||
477 | index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
478 | break; | ||||||||||||
479 | } | ||||||||||||
480 | case JVM_CONSTANT_NameAndType: { | ||||||||||||
481 | if (!_need_verify) break; | ||||||||||||
482 | const int name_ref_index = cp->name_ref_index_at(index); | ||||||||||||
483 | const int signature_ref_index = cp->signature_ref_index_at(index); | ||||||||||||
484 | check_property(valid_symbol_at(name_ref_index), | ||||||||||||
485 | "Invalid constant pool index %u in class file %s", | ||||||||||||
486 | name_ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
487 | check_property(valid_symbol_at(signature_ref_index), | ||||||||||||
488 | "Invalid constant pool index %u in class file %s", | ||||||||||||
489 | signature_ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
490 | break; | ||||||||||||
491 | } | ||||||||||||
492 | case JVM_CONSTANT_Utf8: | ||||||||||||
493 | break; | ||||||||||||
494 | case JVM_CONSTANT_UnresolvedClass: // fall-through | ||||||||||||
495 | case JVM_CONSTANT_UnresolvedClassInError: { | ||||||||||||
496 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 496); ::breakpoint(); } while (0); // Only JVM_CONSTANT_ClassIndex should be present | ||||||||||||
497 | break; | ||||||||||||
498 | } | ||||||||||||
499 | case JVM_CONSTANT_ClassIndex: { | ||||||||||||
500 | const int class_index = cp->klass_index_at(index); | ||||||||||||
501 | check_property(valid_symbol_at(class_index), | ||||||||||||
502 | "Invalid constant pool index %u in class file %s", | ||||||||||||
503 | class_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
504 | cp->unresolved_klass_at_put(index, class_index, num_klasses++); | ||||||||||||
505 | break; | ||||||||||||
506 | } | ||||||||||||
507 | case JVM_CONSTANT_StringIndex: { | ||||||||||||
508 | const int string_index = cp->string_index_at(index); | ||||||||||||
509 | check_property(valid_symbol_at(string_index), | ||||||||||||
510 | "Invalid constant pool index %u in class file %s", | ||||||||||||
511 | string_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
512 | Symbol* const sym = cp->symbol_at(string_index); | ||||||||||||
513 | cp->unresolved_string_at_put(index, sym); | ||||||||||||
514 | break; | ||||||||||||
515 | } | ||||||||||||
516 | case JVM_CONSTANT_MethodHandle: { | ||||||||||||
517 | const int ref_index = cp->method_handle_index_at(index); | ||||||||||||
518 | check_property(valid_cp_range(ref_index, length), | ||||||||||||
519 | "Invalid constant pool index %u in class file %s", | ||||||||||||
520 | ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
521 | const constantTag tag = cp->tag_at(ref_index); | ||||||||||||
522 | const int ref_kind = cp->method_handle_ref_kind_at(index); | ||||||||||||
523 | |||||||||||||
524 | switch (ref_kind) { | ||||||||||||
525 | case JVM_REF_getField: | ||||||||||||
526 | case JVM_REF_getStatic: | ||||||||||||
527 | case JVM_REF_putField: | ||||||||||||
528 | case JVM_REF_putStatic: { | ||||||||||||
529 | check_property( | ||||||||||||
530 | tag.is_field(), | ||||||||||||
531 | "Invalid constant pool index %u in class file %s (not a field)", | ||||||||||||
532 | ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
533 | break; | ||||||||||||
534 | } | ||||||||||||
535 | case JVM_REF_invokeVirtual: | ||||||||||||
536 | case JVM_REF_newInvokeSpecial: { | ||||||||||||
537 | check_property( | ||||||||||||
538 | tag.is_method(), | ||||||||||||
539 | "Invalid constant pool index %u in class file %s (not a method)", | ||||||||||||
540 | ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
541 | break; | ||||||||||||
542 | } | ||||||||||||
543 | case JVM_REF_invokeStatic: | ||||||||||||
544 | case JVM_REF_invokeSpecial: { | ||||||||||||
545 | check_property( | ||||||||||||
546 | tag.is_method() || | ||||||||||||
547 | ((_major_version >= JAVA_8_VERSION52) && tag.is_interface_method()), | ||||||||||||
548 | "Invalid constant pool index %u in class file %s (not a method)", | ||||||||||||
549 | ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
550 | break; | ||||||||||||
551 | } | ||||||||||||
552 | case JVM_REF_invokeInterface: { | ||||||||||||
553 | check_property( | ||||||||||||
554 | tag.is_interface_method(), | ||||||||||||
555 | "Invalid constant pool index %u in class file %s (not an interface method)", | ||||||||||||
556 | ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
557 | break; | ||||||||||||
558 | } | ||||||||||||
559 | default: { | ||||||||||||
560 | classfile_parse_error( | ||||||||||||
561 | "Bad method handle kind at constant pool index %u in class file %s", | ||||||||||||
562 | index, THREAD__the_thread__); | ||||||||||||
563 | return; | ||||||||||||
564 | } | ||||||||||||
565 | } // switch(refkind) | ||||||||||||
566 | // Keep the ref_index unchanged. It will be indirected at link-time. | ||||||||||||
567 | break; | ||||||||||||
568 | } // case MethodHandle | ||||||||||||
569 | case JVM_CONSTANT_MethodType: { | ||||||||||||
570 | const int ref_index = cp->method_type_index_at(index); | ||||||||||||
571 | check_property(valid_symbol_at(ref_index), | ||||||||||||
572 | "Invalid constant pool index %u in class file %s", | ||||||||||||
573 | ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
574 | break; | ||||||||||||
575 | } | ||||||||||||
576 | case JVM_CONSTANT_Dynamic: { | ||||||||||||
577 | const int name_and_type_ref_index = | ||||||||||||
578 | cp->bootstrap_name_and_type_ref_index_at(index); | ||||||||||||
579 | |||||||||||||
580 | check_property(valid_cp_range(name_and_type_ref_index, length) && | ||||||||||||
581 | cp->tag_at(name_and_type_ref_index).is_name_and_type(), | ||||||||||||
582 | "Invalid constant pool index %u in class file %s", | ||||||||||||
583 | name_and_type_ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
584 | // bootstrap specifier index must be checked later, | ||||||||||||
585 | // when BootstrapMethods attr is available | ||||||||||||
586 | |||||||||||||
587 | // Mark the constant pool as having a CONSTANT_Dynamic_info structure | ||||||||||||
588 | cp->set_has_dynamic_constant(); | ||||||||||||
589 | break; | ||||||||||||
590 | } | ||||||||||||
591 | case JVM_CONSTANT_InvokeDynamic: { | ||||||||||||
592 | const int name_and_type_ref_index = | ||||||||||||
593 | cp->bootstrap_name_and_type_ref_index_at(index); | ||||||||||||
594 | |||||||||||||
595 | check_property(valid_cp_range(name_and_type_ref_index, length) && | ||||||||||||
596 | cp->tag_at(name_and_type_ref_index).is_name_and_type(), | ||||||||||||
597 | "Invalid constant pool index %u in class file %s", | ||||||||||||
598 | name_and_type_ref_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
599 | // bootstrap specifier index must be checked later, | ||||||||||||
600 | // when BootstrapMethods attr is available | ||||||||||||
601 | break; | ||||||||||||
602 | } | ||||||||||||
603 | default: { | ||||||||||||
604 | fatal("bad constant pool tag value %u", cp->tag_at(index).value())do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 604, "bad constant pool tag value %u", cp->tag_at(index) .value()); ::breakpoint(); } while (0); | ||||||||||||
605 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 605); ::breakpoint(); } while (0); | ||||||||||||
606 | break; | ||||||||||||
607 | } | ||||||||||||
608 | } // switch(tag) | ||||||||||||
609 | } // end of for | ||||||||||||
610 | |||||||||||||
611 | cp->allocate_resolved_klasses(_loader_data, num_klasses, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
612 | |||||||||||||
613 | if (!_need_verify) { | ||||||||||||
614 | return; | ||||||||||||
615 | } | ||||||||||||
616 | |||||||||||||
617 | // second verification pass - checks the strings are of the right format. | ||||||||||||
618 | // but not yet to the other entries | ||||||||||||
619 | for (index = 1; index < length; index++) { | ||||||||||||
620 | const jbyte tag = cp->tag_at(index).value(); | ||||||||||||
621 | switch (tag) { | ||||||||||||
622 | case JVM_CONSTANT_UnresolvedClass: { | ||||||||||||
623 | const Symbol* const class_name = cp->klass_name_at(index); | ||||||||||||
624 | // check the name | ||||||||||||
625 | verify_legal_class_name(class_name, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
626 | break; | ||||||||||||
627 | } | ||||||||||||
628 | case JVM_CONSTANT_NameAndType: { | ||||||||||||
629 | if (_need_verify) { | ||||||||||||
630 | const int sig_index = cp->signature_ref_index_at(index); | ||||||||||||
631 | const int name_index = cp->name_ref_index_at(index); | ||||||||||||
632 | const Symbol* const name = cp->symbol_at(name_index); | ||||||||||||
633 | const Symbol* const sig = cp->symbol_at(sig_index); | ||||||||||||
634 | guarantee_property(sig->utf8_length() != 0, | ||||||||||||
635 | "Illegal zero length constant pool entry at %d in class %s", | ||||||||||||
636 | sig_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
637 | guarantee_property(name->utf8_length() != 0, | ||||||||||||
638 | "Illegal zero length constant pool entry at %d in class %s", | ||||||||||||
639 | name_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
640 | |||||||||||||
641 | if (Signature::is_method(sig)) { | ||||||||||||
642 | // Format check method name and signature | ||||||||||||
643 | verify_legal_method_name(name, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
644 | verify_legal_method_signature(name, sig, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
645 | } else { | ||||||||||||
646 | // Format check field name and signature | ||||||||||||
647 | verify_legal_field_name(name, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
648 | verify_legal_field_signature(name, sig, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
649 | } | ||||||||||||
650 | } | ||||||||||||
651 | break; | ||||||||||||
652 | } | ||||||||||||
653 | case JVM_CONSTANT_Dynamic: { | ||||||||||||
654 | const int name_and_type_ref_index = | ||||||||||||
655 | cp->name_and_type_ref_index_at(index); | ||||||||||||
656 | // already verified to be utf8 | ||||||||||||
657 | const int name_ref_index = | ||||||||||||
658 | cp->name_ref_index_at(name_and_type_ref_index); | ||||||||||||
659 | // already verified to be utf8 | ||||||||||||
660 | const int signature_ref_index = | ||||||||||||
661 | cp->signature_ref_index_at(name_and_type_ref_index); | ||||||||||||
662 | const Symbol* const name = cp->symbol_at(name_ref_index); | ||||||||||||
663 | const Symbol* const signature = cp->symbol_at(signature_ref_index); | ||||||||||||
664 | if (_need_verify) { | ||||||||||||
665 | // CONSTANT_Dynamic's name and signature are verified above, when iterating NameAndType_info. | ||||||||||||
666 | // Need only to be sure signature is the right type. | ||||||||||||
667 | if (Signature::is_method(signature)) { | ||||||||||||
668 | throwIllegalSignature("CONSTANT_Dynamic", name, signature, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
669 | } | ||||||||||||
670 | } | ||||||||||||
671 | break; | ||||||||||||
672 | } | ||||||||||||
673 | case JVM_CONSTANT_InvokeDynamic: | ||||||||||||
674 | case JVM_CONSTANT_Fieldref: | ||||||||||||
675 | case JVM_CONSTANT_Methodref: | ||||||||||||
676 | case JVM_CONSTANT_InterfaceMethodref: { | ||||||||||||
677 | const int name_and_type_ref_index = | ||||||||||||
678 | cp->name_and_type_ref_index_at(index); | ||||||||||||
679 | // already verified to be utf8 | ||||||||||||
680 | const int name_ref_index = | ||||||||||||
681 | cp->name_ref_index_at(name_and_type_ref_index); | ||||||||||||
682 | // already verified to be utf8 | ||||||||||||
683 | const int signature_ref_index = | ||||||||||||
684 | cp->signature_ref_index_at(name_and_type_ref_index); | ||||||||||||
685 | const Symbol* const name = cp->symbol_at(name_ref_index); | ||||||||||||
686 | const Symbol* const signature = cp->symbol_at(signature_ref_index); | ||||||||||||
687 | if (tag == JVM_CONSTANT_Fieldref) { | ||||||||||||
688 | if (_need_verify) { | ||||||||||||
689 | // Field name and signature are verified above, when iterating NameAndType_info. | ||||||||||||
690 | // Need only to be sure signature is non-zero length and the right type. | ||||||||||||
691 | if (Signature::is_method(signature)) { | ||||||||||||
692 | throwIllegalSignature("Field", name, signature, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
693 | } | ||||||||||||
694 | } | ||||||||||||
695 | } else { | ||||||||||||
696 | if (_need_verify) { | ||||||||||||
697 | // Method name and signature are individually verified above, when iterating | ||||||||||||
698 | // NameAndType_info. Need to check here that signature is non-zero length and | ||||||||||||
699 | // the right type. | ||||||||||||
700 | if (!Signature::is_method(signature)) { | ||||||||||||
701 | throwIllegalSignature("Method", name, signature, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
702 | } | ||||||||||||
703 | } | ||||||||||||
704 | // If a class method name begins with '<', it must be "<init>" and have void signature. | ||||||||||||
705 | const unsigned int name_len = name->utf8_length(); | ||||||||||||
706 | if (tag == JVM_CONSTANT_Methodref && name_len != 0 && | ||||||||||||
707 | name->char_at(0) == JVM_SIGNATURE_SPECIAL) { | ||||||||||||
708 | if (name != vmSymbols::object_initializer_name()) { | ||||||||||||
709 | classfile_parse_error( | ||||||||||||
710 | "Bad method name at constant pool index %u in class file %s", | ||||||||||||
711 | name_ref_index, THREAD__the_thread__); | ||||||||||||
712 | return; | ||||||||||||
713 | } else if (!Signature::is_void_method(signature)) { // must have void signature. | ||||||||||||
714 | throwIllegalSignature("Method", name, signature, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
715 | } | ||||||||||||
716 | } | ||||||||||||
717 | } | ||||||||||||
718 | break; | ||||||||||||
719 | } | ||||||||||||
720 | case JVM_CONSTANT_MethodHandle: { | ||||||||||||
721 | const int ref_index = cp->method_handle_index_at(index); | ||||||||||||
722 | const int ref_kind = cp->method_handle_ref_kind_at(index); | ||||||||||||
723 | switch (ref_kind) { | ||||||||||||
724 | case JVM_REF_invokeVirtual: | ||||||||||||
725 | case JVM_REF_invokeStatic: | ||||||||||||
726 | case JVM_REF_invokeSpecial: | ||||||||||||
727 | case JVM_REF_newInvokeSpecial: { | ||||||||||||
728 | const int name_and_type_ref_index = | ||||||||||||
729 | cp->name_and_type_ref_index_at(ref_index); | ||||||||||||
730 | const int name_ref_index = | ||||||||||||
731 | cp->name_ref_index_at(name_and_type_ref_index); | ||||||||||||
732 | const Symbol* const name = cp->symbol_at(name_ref_index); | ||||||||||||
733 | if (ref_kind == JVM_REF_newInvokeSpecial) { | ||||||||||||
734 | if (name != vmSymbols::object_initializer_name()) { | ||||||||||||
735 | classfile_parse_error( | ||||||||||||
736 | "Bad constructor name at constant pool index %u in class file %s", | ||||||||||||
737 | name_ref_index, THREAD__the_thread__); | ||||||||||||
738 | return; | ||||||||||||
739 | } | ||||||||||||
740 | } else { | ||||||||||||
741 | if (name == vmSymbols::object_initializer_name()) { | ||||||||||||
742 | classfile_parse_error( | ||||||||||||
743 | "Bad method name at constant pool index %u in class file %s", | ||||||||||||
744 | name_ref_index, THREAD__the_thread__); | ||||||||||||
745 | return; | ||||||||||||
746 | } | ||||||||||||
747 | } | ||||||||||||
748 | break; | ||||||||||||
749 | } | ||||||||||||
750 | // Other ref_kinds are already fully checked in previous pass. | ||||||||||||
751 | } // switch(ref_kind) | ||||||||||||
752 | break; | ||||||||||||
753 | } | ||||||||||||
754 | case JVM_CONSTANT_MethodType: { | ||||||||||||
755 | const Symbol* const no_name = vmSymbols::type_name(); // place holder | ||||||||||||
756 | const Symbol* const signature = cp->method_type_signature_at(index); | ||||||||||||
757 | verify_legal_method_signature(no_name, signature, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
758 | break; | ||||||||||||
759 | } | ||||||||||||
760 | case JVM_CONSTANT_Utf8: { | ||||||||||||
761 | assert(cp->symbol_at(index)->refcount() != 0, "count corrupted")do { if (!(cp->symbol_at(index)->refcount() != 0)) { (* g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 761, "assert(" "cp->symbol_at(index)->refcount() != 0" ") failed", "count corrupted"); ::breakpoint(); } } while (0 ); | ||||||||||||
762 | } | ||||||||||||
763 | } // switch(tag) | ||||||||||||
764 | } // end of for | ||||||||||||
765 | } | ||||||||||||
766 | |||||||||||||
767 | class NameSigHash: public ResourceObj { | ||||||||||||
768 | public: | ||||||||||||
769 | const Symbol* _name; // name | ||||||||||||
770 | const Symbol* _sig; // signature | ||||||||||||
771 | NameSigHash* _next; // Next entry in hash table | ||||||||||||
772 | }; | ||||||||||||
773 | |||||||||||||
774 | static const int HASH_ROW_SIZE = 256; | ||||||||||||
775 | |||||||||||||
776 | static unsigned int hash(const Symbol* name, const Symbol* sig) { | ||||||||||||
777 | unsigned int raw_hash = 0; | ||||||||||||
778 | raw_hash += ((unsigned int)(uintptr_t)name) >> (LogHeapWordSize + 2); | ||||||||||||
779 | raw_hash += ((unsigned int)(uintptr_t)sig) >> LogHeapWordSize; | ||||||||||||
780 | |||||||||||||
781 | return (raw_hash + (unsigned int)(uintptr_t)name) % HASH_ROW_SIZE; | ||||||||||||
782 | } | ||||||||||||
783 | |||||||||||||
784 | |||||||||||||
785 | static void initialize_hashtable(NameSigHash** table) { | ||||||||||||
786 | memset((void*)table, 0, sizeof(NameSigHash*) * HASH_ROW_SIZE); | ||||||||||||
787 | } | ||||||||||||
788 | // Return false if the name/sig combination is found in table. | ||||||||||||
789 | // Return true if no duplicate is found. And name/sig is added as a new entry in table. | ||||||||||||
790 | // The old format checker uses heap sort to find duplicates. | ||||||||||||
791 | // NOTE: caller should guarantee that GC doesn't happen during the life cycle | ||||||||||||
792 | // of table since we don't expect Symbol*'s to move. | ||||||||||||
793 | static bool put_after_lookup(const Symbol* name, const Symbol* sig, NameSigHash** table) { | ||||||||||||
794 | assert(name != NULL, "name in constant pool is NULL")do { if (!(name != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 794, "assert(" "name != __null" ") failed", "name in constant pool is NULL" ); ::breakpoint(); } } while (0); | ||||||||||||
795 | |||||||||||||
796 | // First lookup for duplicates | ||||||||||||
797 | int index = hash(name, sig); | ||||||||||||
798 | NameSigHash* entry = table[index]; | ||||||||||||
799 | while (entry != NULL__null) { | ||||||||||||
800 | if (entry->_name == name && entry->_sig == sig) { | ||||||||||||
801 | return false; | ||||||||||||
802 | } | ||||||||||||
803 | entry = entry->_next; | ||||||||||||
804 | } | ||||||||||||
805 | |||||||||||||
806 | // No duplicate is found, allocate a new entry and fill it. | ||||||||||||
807 | entry = new NameSigHash(); | ||||||||||||
808 | entry->_name = name; | ||||||||||||
809 | entry->_sig = sig; | ||||||||||||
810 | |||||||||||||
811 | // Insert into hash table | ||||||||||||
812 | entry->_next = table[index]; | ||||||||||||
813 | table[index] = entry; | ||||||||||||
814 | |||||||||||||
815 | return true; | ||||||||||||
816 | } | ||||||||||||
817 | |||||||||||||
818 | // Side-effects: populates the _local_interfaces field | ||||||||||||
819 | void ClassFileParser::parse_interfaces(const ClassFileStream* const stream, | ||||||||||||
820 | const int itfs_len, | ||||||||||||
821 | ConstantPool* const cp, | ||||||||||||
822 | bool* const has_nonstatic_concrete_methods, | ||||||||||||
823 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
824 | assert(stream != NULL, "invariant")do { if (!(stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 824, "assert(" "stream != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
825 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 825, "assert(" "cp != __null" ") failed", "invariant"); ::breakpoint (); } } while (0); | ||||||||||||
826 | assert(has_nonstatic_concrete_methods != NULL, "invariant")do { if (!(has_nonstatic_concrete_methods != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 826, "assert(" "has_nonstatic_concrete_methods != __null" ") failed" , "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
827 | |||||||||||||
828 | if (itfs_len == 0) { | ||||||||||||
829 | _local_interfaces = Universe::the_empty_instance_klass_array(); | ||||||||||||
830 | } else { | ||||||||||||
831 | assert(itfs_len > 0, "only called for len>0")do { if (!(itfs_len > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 831, "assert(" "itfs_len > 0" ") failed", "only called for len>0" ); ::breakpoint(); } } while (0); | ||||||||||||
832 | _local_interfaces = MetadataFactory::new_array<InstanceKlass*>(_loader_data, itfs_len, NULL__null, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
833 | |||||||||||||
834 | int index; | ||||||||||||
835 | for (index = 0; index < itfs_len; index++) { | ||||||||||||
836 | const u2 interface_index = stream->get_u2(CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
837 | Klass* interf; | ||||||||||||
838 | check_property( | ||||||||||||
839 | valid_klass_reference_at(interface_index), | ||||||||||||
840 | "Interface name has bad constant pool index %u in class file %s", | ||||||||||||
841 | interface_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
842 | if (cp->tag_at(interface_index).is_klass()) { | ||||||||||||
843 | interf = cp->resolved_klass_at(interface_index); | ||||||||||||
844 | } else { | ||||||||||||
845 | Symbol* const unresolved_klass = cp->klass_name_at(interface_index); | ||||||||||||
846 | |||||||||||||
847 | // Don't need to check legal name because it's checked when parsing constant pool. | ||||||||||||
848 | // But need to make sure it's not an array type. | ||||||||||||
849 | guarantee_property(unresolved_klass->char_at(0) != JVM_SIGNATURE_ARRAY, | ||||||||||||
850 | "Bad interface name in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
851 | |||||||||||||
852 | // Call resolve_super so class circularity is checked | ||||||||||||
853 | interf = SystemDictionary::resolve_super_or_fail( | ||||||||||||
854 | _class_name, | ||||||||||||
855 | unresolved_klass, | ||||||||||||
856 | Handle(THREAD__the_thread__, _loader_data->class_loader()), | ||||||||||||
857 | _protection_domain, | ||||||||||||
858 | false, | ||||||||||||
859 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
860 | } | ||||||||||||
861 | |||||||||||||
862 | if (!interf->is_interface()) { | ||||||||||||
863 | THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 867, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s can not implement %s, because it is not an interface (%s)" , _class_name->as_klass_external_name(), interf->external_name (), interf->class_in_module_of_loader())); return; } | ||||||||||||
864 | err_msg("class %s can not implement %s, because it is not an interface (%s)",{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 867, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s can not implement %s, because it is not an interface (%s)" , _class_name->as_klass_external_name(), interf->external_name (), interf->class_in_module_of_loader())); return; } | ||||||||||||
865 | _class_name->as_klass_external_name(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 867, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s can not implement %s, because it is not an interface (%s)" , _class_name->as_klass_external_name(), interf->external_name (), interf->class_in_module_of_loader())); return; } | ||||||||||||
866 | interf->external_name(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 867, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s can not implement %s, because it is not an interface (%s)" , _class_name->as_klass_external_name(), interf->external_name (), interf->class_in_module_of_loader())); return; } | ||||||||||||
867 | interf->class_in_module_of_loader())){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 867, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s can not implement %s, because it is not an interface (%s)" , _class_name->as_klass_external_name(), interf->external_name (), interf->class_in_module_of_loader())); return; }; | ||||||||||||
868 | } | ||||||||||||
869 | |||||||||||||
870 | if (InstanceKlass::cast(interf)->has_nonstatic_concrete_methods()) { | ||||||||||||
871 | *has_nonstatic_concrete_methods = true; | ||||||||||||
872 | } | ||||||||||||
873 | _local_interfaces->at_put(index, InstanceKlass::cast(interf)); | ||||||||||||
874 | } | ||||||||||||
875 | |||||||||||||
876 | if (!_need_verify || itfs_len <= 1) { | ||||||||||||
877 | return; | ||||||||||||
878 | } | ||||||||||||
879 | |||||||||||||
880 | // Check if there's any duplicates in interfaces | ||||||||||||
881 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
882 | NameSigHash** interface_names = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD,(NameSigHash**) resource_allocate_bytes(__the_thread__, (HASH_ROW_SIZE ) * sizeof(NameSigHash*)) | ||||||||||||
883 | NameSigHash*,(NameSigHash**) resource_allocate_bytes(__the_thread__, (HASH_ROW_SIZE ) * sizeof(NameSigHash*)) | ||||||||||||
884 | HASH_ROW_SIZE)(NameSigHash**) resource_allocate_bytes(__the_thread__, (HASH_ROW_SIZE ) * sizeof(NameSigHash*)); | ||||||||||||
885 | initialize_hashtable(interface_names); | ||||||||||||
886 | bool dup = false; | ||||||||||||
887 | const Symbol* name = NULL__null; | ||||||||||||
888 | { | ||||||||||||
889 | debug_only(NoSafepointVerifier nsv;)NoSafepointVerifier nsv; | ||||||||||||
890 | for (index = 0; index < itfs_len; index++) { | ||||||||||||
891 | const InstanceKlass* const k = _local_interfaces->at(index); | ||||||||||||
892 | name = k->name(); | ||||||||||||
893 | // If no duplicates, add (name, NULL) in hashtable interface_names. | ||||||||||||
894 | if (!put_after_lookup(name, NULL__null, interface_names)) { | ||||||||||||
895 | dup = true; | ||||||||||||
896 | break; | ||||||||||||
897 | } | ||||||||||||
898 | } | ||||||||||||
899 | } | ||||||||||||
900 | if (dup) { | ||||||||||||
901 | classfile_parse_error("Duplicate interface name \"%s\" in class file %s", | ||||||||||||
902 | name->as_C_string(), THREAD__the_thread__); | ||||||||||||
903 | } | ||||||||||||
904 | } | ||||||||||||
905 | } | ||||||||||||
906 | |||||||||||||
907 | void ClassFileParser::verify_constantvalue(const ConstantPool* const cp, | ||||||||||||
908 | int constantvalue_index, | ||||||||||||
909 | int signature_index, | ||||||||||||
910 | TRAPSJavaThread* __the_thread__) const { | ||||||||||||
911 | // Make sure the constant pool entry is of a type appropriate to this field | ||||||||||||
912 | guarantee_property( | ||||||||||||
913 | (constantvalue_index > 0 && | ||||||||||||
914 | constantvalue_index < cp->length()), | ||||||||||||
915 | "Bad initial value index %u in ConstantValue attribute in class file %s", | ||||||||||||
916 | constantvalue_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
917 | |||||||||||||
918 | const constantTag value_type = cp->tag_at(constantvalue_index); | ||||||||||||
919 | switch(cp->basic_type_for_signature_at(signature_index)) { | ||||||||||||
920 | case T_LONG: { | ||||||||||||
921 | guarantee_property(value_type.is_long(), | ||||||||||||
922 | "Inconsistent constant value type in class file %s", | ||||||||||||
923 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
924 | break; | ||||||||||||
925 | } | ||||||||||||
926 | case T_FLOAT: { | ||||||||||||
927 | guarantee_property(value_type.is_float(), | ||||||||||||
928 | "Inconsistent constant value type in class file %s", | ||||||||||||
929 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
930 | break; | ||||||||||||
931 | } | ||||||||||||
932 | case T_DOUBLE: { | ||||||||||||
933 | guarantee_property(value_type.is_double(), | ||||||||||||
934 | "Inconsistent constant value type in class file %s", | ||||||||||||
935 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
936 | break; | ||||||||||||
937 | } | ||||||||||||
938 | case T_BYTE: | ||||||||||||
939 | case T_CHAR: | ||||||||||||
940 | case T_SHORT: | ||||||||||||
941 | case T_BOOLEAN: | ||||||||||||
942 | case T_INT: { | ||||||||||||
943 | guarantee_property(value_type.is_int(), | ||||||||||||
944 | "Inconsistent constant value type in class file %s", | ||||||||||||
945 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
946 | break; | ||||||||||||
947 | } | ||||||||||||
948 | case T_OBJECT: { | ||||||||||||
949 | guarantee_property((cp->symbol_at(signature_index)->equals("Ljava/lang/String;") | ||||||||||||
950 | && value_type.is_string()), | ||||||||||||
951 | "Bad string initial value in class file %s", | ||||||||||||
952 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
953 | break; | ||||||||||||
954 | } | ||||||||||||
955 | default: { | ||||||||||||
956 | classfile_parse_error("Unable to set initial value %u in class file %s", | ||||||||||||
957 | constantvalue_index, | ||||||||||||
958 | THREAD__the_thread__); | ||||||||||||
959 | } | ||||||||||||
960 | } | ||||||||||||
961 | } | ||||||||||||
962 | |||||||||||||
963 | class AnnotationCollector : public ResourceObj{ | ||||||||||||
964 | public: | ||||||||||||
965 | enum Location { _in_field, _in_method, _in_class }; | ||||||||||||
966 | enum ID { | ||||||||||||
967 | _unknown = 0, | ||||||||||||
968 | _method_CallerSensitive, | ||||||||||||
969 | _method_ForceInline, | ||||||||||||
970 | _method_DontInline, | ||||||||||||
971 | _method_InjectedProfile, | ||||||||||||
972 | _method_LambdaForm_Compiled, | ||||||||||||
973 | _method_Hidden, | ||||||||||||
974 | _method_Scoped, | ||||||||||||
975 | _method_IntrinsicCandidate, | ||||||||||||
976 | _jdk_internal_vm_annotation_Contended, | ||||||||||||
977 | _field_Stable, | ||||||||||||
978 | _jdk_internal_vm_annotation_ReservedStackAccess, | ||||||||||||
979 | _jdk_internal_ValueBased, | ||||||||||||
980 | _annotation_LIMIT | ||||||||||||
981 | }; | ||||||||||||
982 | const Location _location; | ||||||||||||
983 | int _annotations_present; | ||||||||||||
984 | u2 _contended_group; | ||||||||||||
985 | |||||||||||||
986 | AnnotationCollector(Location location) | ||||||||||||
987 | : _location(location), _annotations_present(0), _contended_group(0) | ||||||||||||
988 | { | ||||||||||||
989 | assert((int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte, "")do { if (!((int)_annotation_LIMIT <= (int)sizeof(_annotations_present ) * BitsPerByte)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 989, "assert(" "(int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte" ") failed", ""); ::breakpoint(); } } while (0); | ||||||||||||
990 | } | ||||||||||||
991 | // If this annotation name has an ID, report it (or _none). | ||||||||||||
992 | ID annotation_index(const ClassLoaderData* loader_data, const Symbol* name, bool can_access_vm_annotations); | ||||||||||||
993 | // Set the annotation name: | ||||||||||||
994 | void set_annotation(ID id) { | ||||||||||||
995 | assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob")do { if (!((int)id >= 0 && (int)id < (int)_annotation_LIMIT )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 995, "assert(" "(int)id >= 0 && (int)id < (int)_annotation_LIMIT" ") failed", "oob"); ::breakpoint(); } } while (0); | ||||||||||||
996 | _annotations_present |= nth_bit((int)id)((((int)id) >= BitsPerWord) ? 0 : (OneBit << ((int)id ))); | ||||||||||||
997 | } | ||||||||||||
998 | |||||||||||||
999 | void remove_annotation(ID id) { | ||||||||||||
1000 | assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob")do { if (!((int)id >= 0 && (int)id < (int)_annotation_LIMIT )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1000, "assert(" "(int)id >= 0 && (int)id < (int)_annotation_LIMIT" ") failed", "oob"); ::breakpoint(); } } while (0); | ||||||||||||
1001 | _annotations_present &= ~nth_bit((int)id)((((int)id) >= BitsPerWord) ? 0 : (OneBit << ((int)id ))); | ||||||||||||
1002 | } | ||||||||||||
1003 | |||||||||||||
1004 | // Report if the annotation is present. | ||||||||||||
1005 | bool has_any_annotations() const { return _annotations_present != 0; } | ||||||||||||
1006 | bool has_annotation(ID id) const { return (nth_bit((int)id)((((int)id) >= BitsPerWord) ? 0 : (OneBit << ((int)id ))) & _annotations_present) != 0; } | ||||||||||||
1007 | |||||||||||||
1008 | void set_contended_group(u2 group) { _contended_group = group; } | ||||||||||||
1009 | u2 contended_group() const { return _contended_group; } | ||||||||||||
1010 | |||||||||||||
1011 | bool is_contended() const { return has_annotation(_jdk_internal_vm_annotation_Contended); } | ||||||||||||
1012 | |||||||||||||
1013 | void set_stable(bool stable) { set_annotation(_field_Stable); } | ||||||||||||
1014 | bool is_stable() const { return has_annotation(_field_Stable); } | ||||||||||||
1015 | }; | ||||||||||||
1016 | |||||||||||||
1017 | // This class also doubles as a holder for metadata cleanup. | ||||||||||||
1018 | class ClassFileParser::FieldAnnotationCollector : public AnnotationCollector { | ||||||||||||
1019 | private: | ||||||||||||
1020 | ClassLoaderData* _loader_data; | ||||||||||||
1021 | AnnotationArray* _field_annotations; | ||||||||||||
1022 | AnnotationArray* _field_type_annotations; | ||||||||||||
1023 | public: | ||||||||||||
1024 | FieldAnnotationCollector(ClassLoaderData* loader_data) : | ||||||||||||
1025 | AnnotationCollector(_in_field), | ||||||||||||
1026 | _loader_data(loader_data), | ||||||||||||
1027 | _field_annotations(NULL__null), | ||||||||||||
1028 | _field_type_annotations(NULL__null) {} | ||||||||||||
1029 | ~FieldAnnotationCollector(); | ||||||||||||
1030 | void apply_to(FieldInfo* f); | ||||||||||||
1031 | AnnotationArray* field_annotations() { return _field_annotations; } | ||||||||||||
1032 | AnnotationArray* field_type_annotations() { return _field_type_annotations; } | ||||||||||||
1033 | |||||||||||||
1034 | void set_field_annotations(AnnotationArray* a) { _field_annotations = a; } | ||||||||||||
1035 | void set_field_type_annotations(AnnotationArray* a) { _field_type_annotations = a; } | ||||||||||||
1036 | }; | ||||||||||||
1037 | |||||||||||||
1038 | class MethodAnnotationCollector : public AnnotationCollector{ | ||||||||||||
1039 | public: | ||||||||||||
1040 | MethodAnnotationCollector() : AnnotationCollector(_in_method) { } | ||||||||||||
1041 | void apply_to(const methodHandle& m); | ||||||||||||
1042 | }; | ||||||||||||
1043 | |||||||||||||
1044 | class ClassFileParser::ClassAnnotationCollector : public AnnotationCollector{ | ||||||||||||
1045 | public: | ||||||||||||
1046 | ClassAnnotationCollector() : AnnotationCollector(_in_class) { } | ||||||||||||
1047 | void apply_to(InstanceKlass* ik); | ||||||||||||
1048 | }; | ||||||||||||
1049 | |||||||||||||
1050 | |||||||||||||
1051 | static int skip_annotation_value(const u1*, int, int); // fwd decl | ||||||||||||
1052 | |||||||||||||
1053 | // Safely increment index by val if does not pass limit | ||||||||||||
1054 | #define SAFE_ADD(index, limit, val)if (index >= limit - val) return limit; index += val; \ | ||||||||||||
1055 | if (index >= limit - val) return limit; \ | ||||||||||||
1056 | index += val; | ||||||||||||
1057 | |||||||||||||
1058 | // Skip an annotation. Return >=limit if there is any problem. | ||||||||||||
1059 | static int skip_annotation(const u1* buffer, int limit, int index) { | ||||||||||||
1060 | assert(buffer != NULL, "invariant")do { if (!(buffer != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1060, "assert(" "buffer != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); | ||||||||||||
1061 | // annotation := atype:u2 do(nmem:u2) {member:u2 value} | ||||||||||||
1062 | // value := switch (tag:u1) { ... } | ||||||||||||
1063 | SAFE_ADD(index, limit, 4)if (index >= limit - 4) return limit; index += 4;; // skip atype and read nmem | ||||||||||||
1064 | int nmem = Bytes::get_Java_u2((address)buffer + index - 2); | ||||||||||||
1065 | while (--nmem >= 0 && index < limit) { | ||||||||||||
1066 | SAFE_ADD(index, limit, 2)if (index >= limit - 2) return limit; index += 2;; // skip member | ||||||||||||
1067 | index = skip_annotation_value(buffer, limit, index); | ||||||||||||
1068 | } | ||||||||||||
1069 | return index; | ||||||||||||
1070 | } | ||||||||||||
1071 | |||||||||||||
1072 | // Skip an annotation value. Return >=limit if there is any problem. | ||||||||||||
1073 | static int skip_annotation_value(const u1* buffer, int limit, int index) { | ||||||||||||
1074 | assert(buffer != NULL, "invariant")do { if (!(buffer != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1074, "assert(" "buffer != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); | ||||||||||||
1075 | |||||||||||||
1076 | // value := switch (tag:u1) { | ||||||||||||
1077 | // case B, C, I, S, Z, D, F, J, c: con:u2; | ||||||||||||
1078 | // case e: e_class:u2 e_name:u2; | ||||||||||||
1079 | // case s: s_con:u2; | ||||||||||||
1080 | // case [: do(nval:u2) {value}; | ||||||||||||
1081 | // case @: annotation; | ||||||||||||
1082 | // case s: s_con:u2; | ||||||||||||
1083 | // } | ||||||||||||
1084 | SAFE_ADD(index, limit, 1)if (index >= limit - 1) return limit; index += 1;; // read tag | ||||||||||||
1085 | const u1 tag = buffer[index - 1]; | ||||||||||||
1086 | switch (tag) { | ||||||||||||
1087 | case 'B': | ||||||||||||
1088 | case 'C': | ||||||||||||
1089 | case 'I': | ||||||||||||
1090 | case 'S': | ||||||||||||
1091 | case 'Z': | ||||||||||||
1092 | case 'D': | ||||||||||||
1093 | case 'F': | ||||||||||||
1094 | case 'J': | ||||||||||||
1095 | case 'c': | ||||||||||||
1096 | case 's': | ||||||||||||
1097 | SAFE_ADD(index, limit, 2)if (index >= limit - 2) return limit; index += 2;; // skip con or s_con | ||||||||||||
1098 | break; | ||||||||||||
1099 | case 'e': | ||||||||||||
1100 | SAFE_ADD(index, limit, 4)if (index >= limit - 4) return limit; index += 4;; // skip e_class, e_name | ||||||||||||
1101 | break; | ||||||||||||
1102 | case '[': | ||||||||||||
1103 | { | ||||||||||||
1104 | SAFE_ADD(index, limit, 2)if (index >= limit - 2) return limit; index += 2;; // read nval | ||||||||||||
1105 | int nval = Bytes::get_Java_u2((address)buffer + index - 2); | ||||||||||||
1106 | while (--nval >= 0 && index < limit) { | ||||||||||||
1107 | index = skip_annotation_value(buffer, limit, index); | ||||||||||||
1108 | } | ||||||||||||
1109 | } | ||||||||||||
1110 | break; | ||||||||||||
1111 | case '@': | ||||||||||||
1112 | index = skip_annotation(buffer, limit, index); | ||||||||||||
1113 | break; | ||||||||||||
1114 | default: | ||||||||||||
1115 | return limit; // bad tag byte | ||||||||||||
1116 | } | ||||||||||||
1117 | return index; | ||||||||||||
1118 | } | ||||||||||||
1119 | |||||||||||||
1120 | // Sift through annotations, looking for those significant to the VM: | ||||||||||||
1121 | static void parse_annotations(const ConstantPool* const cp, | ||||||||||||
1122 | const u1* buffer, int limit, | ||||||||||||
1123 | AnnotationCollector* coll, | ||||||||||||
1124 | ClassLoaderData* loader_data, | ||||||||||||
1125 | const bool can_access_vm_annotations) { | ||||||||||||
1126 | |||||||||||||
1127 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1127, "assert(" "cp != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
1128 | assert(buffer != NULL, "invariant")do { if (!(buffer != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1128, "assert(" "buffer != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); | ||||||||||||
1129 | assert(coll != NULL, "invariant")do { if (!(coll != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1129, "assert(" "coll != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
1130 | assert(loader_data != NULL, "invariant")do { if (!(loader_data != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1130, "assert(" "loader_data != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
1131 | |||||||||||||
1132 | // annotations := do(nann:u2) {annotation} | ||||||||||||
1133 | int index = 2; // read nann | ||||||||||||
1134 | if (index >= limit) return; | ||||||||||||
1135 | int nann = Bytes::get_Java_u2((address)buffer + index - 2); | ||||||||||||
1136 | enum { // initial annotation layout | ||||||||||||
1137 | atype_off = 0, // utf8 such as 'Ljava/lang/annotation/Retention;' | ||||||||||||
1138 | count_off = 2, // u2 such as 1 (one value) | ||||||||||||
1139 | member_off = 4, // utf8 such as 'value' | ||||||||||||
1140 | tag_off = 6, // u1 such as 'c' (type) or 'e' (enum) | ||||||||||||
1141 | e_tag_val = 'e', | ||||||||||||
1142 | e_type_off = 7, // utf8 such as 'Ljava/lang/annotation/RetentionPolicy;' | ||||||||||||
1143 | e_con_off = 9, // utf8 payload, such as 'SOURCE', 'CLASS', 'RUNTIME' | ||||||||||||
1144 | e_size = 11, // end of 'e' annotation | ||||||||||||
1145 | c_tag_val = 'c', // payload is type | ||||||||||||
1146 | c_con_off = 7, // utf8 payload, such as 'I' | ||||||||||||
1147 | c_size = 9, // end of 'c' annotation | ||||||||||||
1148 | s_tag_val = 's', // payload is String | ||||||||||||
1149 | s_con_off = 7, // utf8 payload, such as 'Ljava/lang/String;' | ||||||||||||
1150 | s_size = 9, | ||||||||||||
1151 | min_size = 6 // smallest possible size (zero members) | ||||||||||||
1152 | }; | ||||||||||||
1153 | // Cannot add min_size to index in case of overflow MAX_INT | ||||||||||||
1154 | while ((--nann) >= 0 && (index - 2 <= limit - min_size)) { | ||||||||||||
1155 | int index0 = index; | ||||||||||||
1156 | index = skip_annotation(buffer, limit, index); | ||||||||||||
1157 | const u1* const abase = buffer + index0; | ||||||||||||
1158 | const int atype = Bytes::get_Java_u2((address)abase + atype_off); | ||||||||||||
1159 | const int count = Bytes::get_Java_u2((address)abase + count_off); | ||||||||||||
1160 | const Symbol* const aname = check_symbol_at(cp, atype); | ||||||||||||
1161 | if (aname == NULL__null) break; // invalid annotation name | ||||||||||||
1162 | const Symbol* member = NULL__null; | ||||||||||||
1163 | if (count >= 1) { | ||||||||||||
1164 | const int member_index = Bytes::get_Java_u2((address)abase + member_off); | ||||||||||||
1165 | member = check_symbol_at(cp, member_index); | ||||||||||||
1166 | if (member == NULL__null) break; // invalid member name | ||||||||||||
1167 | } | ||||||||||||
1168 | |||||||||||||
1169 | // Here is where parsing particular annotations will take place. | ||||||||||||
1170 | AnnotationCollector::ID id = coll->annotation_index(loader_data, aname, can_access_vm_annotations); | ||||||||||||
1171 | if (AnnotationCollector::_unknown == id) continue; | ||||||||||||
1172 | coll->set_annotation(id); | ||||||||||||
1173 | |||||||||||||
1174 | if (AnnotationCollector::_jdk_internal_vm_annotation_Contended == id) { | ||||||||||||
1175 | // @Contended can optionally specify the contention group. | ||||||||||||
1176 | // | ||||||||||||
1177 | // Contended group defines the equivalence class over the fields: | ||||||||||||
1178 | // the fields within the same contended group are not treated distinct. | ||||||||||||
1179 | // The only exception is default group, which does not incur the | ||||||||||||
1180 | // equivalence. Naturally, contention group for classes is meaningless. | ||||||||||||
1181 | // | ||||||||||||
1182 | // While the contention group is specified as String, annotation | ||||||||||||
1183 | // values are already interned, and we might as well use the constant | ||||||||||||
1184 | // pool index as the group tag. | ||||||||||||
1185 | // | ||||||||||||
1186 | u2 group_index = 0; // default contended group | ||||||||||||
1187 | if (count == 1 | ||||||||||||
1188 | && s_size == (index - index0) // match size | ||||||||||||
1189 | && s_tag_val == *(abase + tag_off) | ||||||||||||
1190 | && member == vmSymbols::value_name()) { | ||||||||||||
1191 | group_index = Bytes::get_Java_u2((address)abase + s_con_off); | ||||||||||||
1192 | if (cp->symbol_at(group_index)->utf8_length() == 0) { | ||||||||||||
1193 | group_index = 0; // default contended group | ||||||||||||
1194 | } | ||||||||||||
1195 | } | ||||||||||||
1196 | coll->set_contended_group(group_index); | ||||||||||||
1197 | } | ||||||||||||
1198 | } | ||||||||||||
1199 | } | ||||||||||||
1200 | |||||||||||||
1201 | |||||||||||||
1202 | // Parse attributes for a field. | ||||||||||||
1203 | void ClassFileParser::parse_field_attributes(const ClassFileStream* const cfs, | ||||||||||||
1204 | u2 attributes_count, | ||||||||||||
1205 | bool is_static, u2 signature_index, | ||||||||||||
1206 | u2* const constantvalue_index_addr, | ||||||||||||
1207 | bool* const is_synthetic_addr, | ||||||||||||
1208 | u2* const generic_signature_index_addr, | ||||||||||||
1209 | ClassFileParser::FieldAnnotationCollector* parsed_annotations, | ||||||||||||
1210 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
1211 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1211, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
1212 | assert(constantvalue_index_addr != NULL, "invariant")do { if (!(constantvalue_index_addr != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1212, "assert(" "constantvalue_index_addr != __null" ") failed" , "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
1213 | assert(is_synthetic_addr != NULL, "invariant")do { if (!(is_synthetic_addr != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1213, "assert(" "is_synthetic_addr != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
1214 | assert(generic_signature_index_addr != NULL, "invariant")do { if (!(generic_signature_index_addr != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1214, "assert(" "generic_signature_index_addr != __null" ") failed" , "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
1215 | assert(parsed_annotations != NULL, "invariant")do { if (!(parsed_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1215, "assert(" "parsed_annotations != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
1216 | assert(attributes_count > 0, "attributes_count should be greater than 0")do { if (!(attributes_count > 0)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1216, "assert(" "attributes_count > 0" ") failed", "attributes_count should be greater than 0" ); ::breakpoint(); } } while (0); | ||||||||||||
1217 | |||||||||||||
1218 | u2 constantvalue_index = 0; | ||||||||||||
1219 | u2 generic_signature_index = 0; | ||||||||||||
1220 | bool is_synthetic = false; | ||||||||||||
1221 | const u1* runtime_visible_annotations = NULL__null; | ||||||||||||
1222 | int runtime_visible_annotations_length = 0; | ||||||||||||
1223 | const u1* runtime_invisible_annotations = NULL__null; | ||||||||||||
1224 | int runtime_invisible_annotations_length = 0; | ||||||||||||
1225 | const u1* runtime_visible_type_annotations = NULL__null; | ||||||||||||
1226 | int runtime_visible_type_annotations_length = 0; | ||||||||||||
1227 | const u1* runtime_invisible_type_annotations = NULL__null; | ||||||||||||
1228 | int runtime_invisible_type_annotations_length = 0; | ||||||||||||
1229 | bool runtime_invisible_annotations_exists = false; | ||||||||||||
1230 | bool runtime_invisible_type_annotations_exists = false; | ||||||||||||
1231 | const ConstantPool* const cp = _cp; | ||||||||||||
1232 | |||||||||||||
1233 | while (attributes_count--) { | ||||||||||||
1234 | cfs->guarantee_more(6, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // attribute_name_index, attribute_length | ||||||||||||
1235 | const u2 attribute_name_index = cfs->get_u2_fast(); | ||||||||||||
1236 | const u4 attribute_length = cfs->get_u4_fast(); | ||||||||||||
1237 | check_property(valid_symbol_at(attribute_name_index), | ||||||||||||
1238 | "Invalid field attribute index %u in class file %s", | ||||||||||||
1239 | attribute_name_index, | ||||||||||||
1240 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1241 | |||||||||||||
1242 | const Symbol* const attribute_name = cp->symbol_at(attribute_name_index); | ||||||||||||
1243 | if (is_static && attribute_name == vmSymbols::tag_constant_value()) { | ||||||||||||
1244 | // ignore if non-static | ||||||||||||
1245 | if (constantvalue_index != 0) { | ||||||||||||
1246 | classfile_parse_error("Duplicate ConstantValue attribute in class file %s", THREAD__the_thread__); | ||||||||||||
1247 | return; | ||||||||||||
1248 | } | ||||||||||||
1249 | check_property( | ||||||||||||
1250 | attribute_length == 2, | ||||||||||||
1251 | "Invalid ConstantValue field attribute length %u in class file %s", | ||||||||||||
1252 | attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1253 | |||||||||||||
1254 | constantvalue_index = cfs->get_u2(CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1255 | if (_need_verify) { | ||||||||||||
1256 | verify_constantvalue(cp, constantvalue_index, signature_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1257 | } | ||||||||||||
1258 | } else if (attribute_name == vmSymbols::tag_synthetic()) { | ||||||||||||
1259 | if (attribute_length != 0) { | ||||||||||||
1260 | classfile_parse_error( | ||||||||||||
1261 | "Invalid Synthetic field attribute length %u in class file %s", | ||||||||||||
1262 | attribute_length, THREAD__the_thread__); | ||||||||||||
1263 | return; | ||||||||||||
1264 | } | ||||||||||||
1265 | is_synthetic = true; | ||||||||||||
1266 | } else if (attribute_name == vmSymbols::tag_deprecated()) { // 4276120 | ||||||||||||
1267 | if (attribute_length != 0) { | ||||||||||||
1268 | classfile_parse_error( | ||||||||||||
1269 | "Invalid Deprecated field attribute length %u in class file %s", | ||||||||||||
1270 | attribute_length, THREAD__the_thread__); | ||||||||||||
1271 | return; | ||||||||||||
1272 | } | ||||||||||||
1273 | } else if (_major_version >= JAVA_1_5_VERSION49) { | ||||||||||||
1274 | if (attribute_name == vmSymbols::tag_signature()) { | ||||||||||||
1275 | if (generic_signature_index != 0) { | ||||||||||||
1276 | classfile_parse_error( | ||||||||||||
1277 | "Multiple Signature attributes for field in class file %s", THREAD__the_thread__); | ||||||||||||
1278 | return; | ||||||||||||
1279 | } | ||||||||||||
1280 | if (attribute_length != 2) { | ||||||||||||
1281 | classfile_parse_error( | ||||||||||||
1282 | "Wrong size %u for field's Signature attribute in class file %s", | ||||||||||||
1283 | attribute_length, THREAD__the_thread__); | ||||||||||||
1284 | return; | ||||||||||||
1285 | } | ||||||||||||
1286 | generic_signature_index = parse_generic_signature_attribute(cfs, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1287 | } else if (attribute_name == vmSymbols::tag_runtime_visible_annotations()) { | ||||||||||||
1288 | if (runtime_visible_annotations != NULL__null) { | ||||||||||||
1289 | classfile_parse_error( | ||||||||||||
1290 | "Multiple RuntimeVisibleAnnotations attributes for field in class file %s", THREAD__the_thread__); | ||||||||||||
1291 | return; | ||||||||||||
1292 | } | ||||||||||||
1293 | runtime_visible_annotations_length = attribute_length; | ||||||||||||
1294 | runtime_visible_annotations = cfs->current(); | ||||||||||||
1295 | assert(runtime_visible_annotations != NULL, "null visible annotations")do { if (!(runtime_visible_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1295, "assert(" "runtime_visible_annotations != __null" ") failed" , "null visible annotations"); ::breakpoint(); } } while (0); | ||||||||||||
1296 | cfs->guarantee_more(runtime_visible_annotations_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1297 | parse_annotations(cp, | ||||||||||||
1298 | runtime_visible_annotations, | ||||||||||||
1299 | runtime_visible_annotations_length, | ||||||||||||
1300 | parsed_annotations, | ||||||||||||
1301 | _loader_data, | ||||||||||||
1302 | _can_access_vm_annotations); | ||||||||||||
1303 | cfs->skip_u1_fast(runtime_visible_annotations_length); | ||||||||||||
1304 | } else if (attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { | ||||||||||||
1305 | if (runtime_invisible_annotations_exists) { | ||||||||||||
1306 | classfile_parse_error( | ||||||||||||
1307 | "Multiple RuntimeInvisibleAnnotations attributes for field in class file %s", THREAD__the_thread__); | ||||||||||||
1308 | return; | ||||||||||||
1309 | } | ||||||||||||
1310 | runtime_invisible_annotations_exists = true; | ||||||||||||
1311 | if (PreserveAllAnnotations) { | ||||||||||||
1312 | runtime_invisible_annotations_length = attribute_length; | ||||||||||||
1313 | runtime_invisible_annotations = cfs->current(); | ||||||||||||
1314 | assert(runtime_invisible_annotations != NULL, "null invisible annotations")do { if (!(runtime_invisible_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1314, "assert(" "runtime_invisible_annotations != __null" ") failed" , "null invisible annotations"); ::breakpoint(); } } while (0 ); | ||||||||||||
1315 | } | ||||||||||||
1316 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1317 | } else if (attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) { | ||||||||||||
1318 | if (runtime_visible_type_annotations != NULL__null) { | ||||||||||||
1319 | classfile_parse_error( | ||||||||||||
1320 | "Multiple RuntimeVisibleTypeAnnotations attributes for field in class file %s", THREAD__the_thread__); | ||||||||||||
1321 | return; | ||||||||||||
1322 | } | ||||||||||||
1323 | runtime_visible_type_annotations_length = attribute_length; | ||||||||||||
1324 | runtime_visible_type_annotations = cfs->current(); | ||||||||||||
1325 | assert(runtime_visible_type_annotations != NULL, "null visible type annotations")do { if (!(runtime_visible_type_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1325, "assert(" "runtime_visible_type_annotations != __null" ") failed", "null visible type annotations"); ::breakpoint() ; } } while (0); | ||||||||||||
1326 | cfs->skip_u1(runtime_visible_type_annotations_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1327 | } else if (attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) { | ||||||||||||
1328 | if (runtime_invisible_type_annotations_exists) { | ||||||||||||
1329 | classfile_parse_error( | ||||||||||||
1330 | "Multiple RuntimeInvisibleTypeAnnotations attributes for field in class file %s", THREAD__the_thread__); | ||||||||||||
1331 | return; | ||||||||||||
1332 | } else { | ||||||||||||
1333 | runtime_invisible_type_annotations_exists = true; | ||||||||||||
1334 | } | ||||||||||||
1335 | if (PreserveAllAnnotations) { | ||||||||||||
1336 | runtime_invisible_type_annotations_length = attribute_length; | ||||||||||||
1337 | runtime_invisible_type_annotations = cfs->current(); | ||||||||||||
1338 | assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations")do { if (!(runtime_invisible_type_annotations != __null)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1338, "assert(" "runtime_invisible_type_annotations != __null" ") failed", "null invisible type annotations"); ::breakpoint (); } } while (0); | ||||||||||||
1339 | } | ||||||||||||
1340 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1341 | } else { | ||||||||||||
1342 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // Skip unknown attributes | ||||||||||||
1343 | } | ||||||||||||
1344 | } else { | ||||||||||||
1345 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // Skip unknown attributes | ||||||||||||
1346 | } | ||||||||||||
1347 | } | ||||||||||||
1348 | |||||||||||||
1349 | *constantvalue_index_addr = constantvalue_index; | ||||||||||||
1350 | *is_synthetic_addr = is_synthetic; | ||||||||||||
1351 | *generic_signature_index_addr = generic_signature_index; | ||||||||||||
1352 | AnnotationArray* a = assemble_annotations(runtime_visible_annotations, | ||||||||||||
1353 | runtime_visible_annotations_length, | ||||||||||||
1354 | runtime_invisible_annotations, | ||||||||||||
1355 | runtime_invisible_annotations_length, | ||||||||||||
1356 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1357 | parsed_annotations->set_field_annotations(a); | ||||||||||||
1358 | a = assemble_annotations(runtime_visible_type_annotations, | ||||||||||||
1359 | runtime_visible_type_annotations_length, | ||||||||||||
1360 | runtime_invisible_type_annotations, | ||||||||||||
1361 | runtime_invisible_type_annotations_length, | ||||||||||||
1362 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1363 | parsed_annotations->set_field_type_annotations(a); | ||||||||||||
1364 | return; | ||||||||||||
1365 | } | ||||||||||||
1366 | |||||||||||||
1367 | |||||||||||||
1368 | // Field allocation types. Used for computing field offsets. | ||||||||||||
1369 | |||||||||||||
1370 | enum FieldAllocationType { | ||||||||||||
1371 | STATIC_OOP, // Oops | ||||||||||||
1372 | STATIC_BYTE, // Boolean, Byte, char | ||||||||||||
1373 | STATIC_SHORT, // shorts | ||||||||||||
1374 | STATIC_WORD, // ints | ||||||||||||
1375 | STATIC_DOUBLE, // aligned long or double | ||||||||||||
1376 | NONSTATIC_OOP, | ||||||||||||
1377 | NONSTATIC_BYTE, | ||||||||||||
1378 | NONSTATIC_SHORT, | ||||||||||||
1379 | NONSTATIC_WORD, | ||||||||||||
1380 | NONSTATIC_DOUBLE, | ||||||||||||
1381 | MAX_FIELD_ALLOCATION_TYPE, | ||||||||||||
1382 | BAD_ALLOCATION_TYPE = -1 | ||||||||||||
1383 | }; | ||||||||||||
1384 | |||||||||||||
1385 | static FieldAllocationType _basic_type_to_atype[2 * (T_CONFLICT + 1)] = { | ||||||||||||
1386 | BAD_ALLOCATION_TYPE, // 0 | ||||||||||||
1387 | BAD_ALLOCATION_TYPE, // 1 | ||||||||||||
1388 | BAD_ALLOCATION_TYPE, // 2 | ||||||||||||
1389 | BAD_ALLOCATION_TYPE, // 3 | ||||||||||||
1390 | NONSTATIC_BYTE , // T_BOOLEAN = 4, | ||||||||||||
1391 | NONSTATIC_SHORT, // T_CHAR = 5, | ||||||||||||
1392 | NONSTATIC_WORD, // T_FLOAT = 6, | ||||||||||||
1393 | NONSTATIC_DOUBLE, // T_DOUBLE = 7, | ||||||||||||
1394 | NONSTATIC_BYTE, // T_BYTE = 8, | ||||||||||||
1395 | NONSTATIC_SHORT, // T_SHORT = 9, | ||||||||||||
1396 | NONSTATIC_WORD, // T_INT = 10, | ||||||||||||
1397 | NONSTATIC_DOUBLE, // T_LONG = 11, | ||||||||||||
1398 | NONSTATIC_OOP, // T_OBJECT = 12, | ||||||||||||
1399 | NONSTATIC_OOP, // T_ARRAY = 13, | ||||||||||||
1400 | BAD_ALLOCATION_TYPE, // T_VOID = 14, | ||||||||||||
1401 | BAD_ALLOCATION_TYPE, // T_ADDRESS = 15, | ||||||||||||
1402 | BAD_ALLOCATION_TYPE, // T_NARROWOOP = 16, | ||||||||||||
1403 | BAD_ALLOCATION_TYPE, // T_METADATA = 17, | ||||||||||||
1404 | BAD_ALLOCATION_TYPE, // T_NARROWKLASS = 18, | ||||||||||||
1405 | BAD_ALLOCATION_TYPE, // T_CONFLICT = 19, | ||||||||||||
1406 | BAD_ALLOCATION_TYPE, // 0 | ||||||||||||
1407 | BAD_ALLOCATION_TYPE, // 1 | ||||||||||||
1408 | BAD_ALLOCATION_TYPE, // 2 | ||||||||||||
1409 | BAD_ALLOCATION_TYPE, // 3 | ||||||||||||
1410 | STATIC_BYTE , // T_BOOLEAN = 4, | ||||||||||||
1411 | STATIC_SHORT, // T_CHAR = 5, | ||||||||||||
1412 | STATIC_WORD, // T_FLOAT = 6, | ||||||||||||
1413 | STATIC_DOUBLE, // T_DOUBLE = 7, | ||||||||||||
1414 | STATIC_BYTE, // T_BYTE = 8, | ||||||||||||
1415 | STATIC_SHORT, // T_SHORT = 9, | ||||||||||||
1416 | STATIC_WORD, // T_INT = 10, | ||||||||||||
1417 | STATIC_DOUBLE, // T_LONG = 11, | ||||||||||||
1418 | STATIC_OOP, // T_OBJECT = 12, | ||||||||||||
1419 | STATIC_OOP, // T_ARRAY = 13, | ||||||||||||
1420 | BAD_ALLOCATION_TYPE, // T_VOID = 14, | ||||||||||||
1421 | BAD_ALLOCATION_TYPE, // T_ADDRESS = 15, | ||||||||||||
1422 | BAD_ALLOCATION_TYPE, // T_NARROWOOP = 16, | ||||||||||||
1423 | BAD_ALLOCATION_TYPE, // T_METADATA = 17, | ||||||||||||
1424 | BAD_ALLOCATION_TYPE, // T_NARROWKLASS = 18, | ||||||||||||
1425 | BAD_ALLOCATION_TYPE, // T_CONFLICT = 19, | ||||||||||||
1426 | }; | ||||||||||||
1427 | |||||||||||||
1428 | static FieldAllocationType basic_type_to_atype(bool is_static, BasicType type) { | ||||||||||||
1429 | assert(type >= T_BOOLEAN && type < T_VOID, "only allowable values")do { if (!(type >= T_BOOLEAN && type < T_VOID)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1429, "assert(" "type >= T_BOOLEAN && type < T_VOID" ") failed", "only allowable values"); ::breakpoint(); } } while (0); | ||||||||||||
1430 | FieldAllocationType result = _basic_type_to_atype[type + (is_static ? (T_CONFLICT + 1) : 0)]; | ||||||||||||
1431 | assert(result != BAD_ALLOCATION_TYPE, "bad type")do { if (!(result != BAD_ALLOCATION_TYPE)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1431, "assert(" "result != BAD_ALLOCATION_TYPE" ") failed", "bad type"); ::breakpoint(); } } while (0); | ||||||||||||
1432 | return result; | ||||||||||||
1433 | } | ||||||||||||
1434 | |||||||||||||
1435 | class ClassFileParser::FieldAllocationCount : public ResourceObj { | ||||||||||||
1436 | public: | ||||||||||||
1437 | u2 count[MAX_FIELD_ALLOCATION_TYPE]; | ||||||||||||
1438 | |||||||||||||
1439 | FieldAllocationCount() { | ||||||||||||
1440 | for (int i = 0; i < MAX_FIELD_ALLOCATION_TYPE; i++) { | ||||||||||||
1441 | count[i] = 0; | ||||||||||||
1442 | } | ||||||||||||
1443 | } | ||||||||||||
1444 | |||||||||||||
1445 | void update(bool is_static, BasicType type) { | ||||||||||||
1446 | FieldAllocationType atype = basic_type_to_atype(is_static, type); | ||||||||||||
1447 | if (atype != BAD_ALLOCATION_TYPE) { | ||||||||||||
1448 | // Make sure there is no overflow with injected fields. | ||||||||||||
1449 | assert(count[atype] < 0xFFFF, "More than 65535 fields")do { if (!(count[atype] < 0xFFFF)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1449, "assert(" "count[atype] < 0xFFFF" ") failed", "More than 65535 fields" ); ::breakpoint(); } } while (0); | ||||||||||||
1450 | count[atype]++; | ||||||||||||
1451 | } | ||||||||||||
1452 | } | ||||||||||||
1453 | }; | ||||||||||||
1454 | |||||||||||||
1455 | // Side-effects: populates the _fields, _fields_annotations, | ||||||||||||
1456 | // _fields_type_annotations fields | ||||||||||||
1457 | void ClassFileParser::parse_fields(const ClassFileStream* const cfs, | ||||||||||||
1458 | bool is_interface, | ||||||||||||
1459 | FieldAllocationCount* const fac, | ||||||||||||
1460 | ConstantPool* cp, | ||||||||||||
1461 | const int cp_size, | ||||||||||||
1462 | u2* const java_fields_count_ptr, | ||||||||||||
1463 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
1464 | |||||||||||||
1465 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1465, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
1466 | assert(fac != NULL, "invariant")do { if (!(fac != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1466, "assert(" "fac != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
1467 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1467, "assert(" "cp != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
1468 | assert(java_fields_count_ptr != NULL, "invariant")do { if (!(java_fields_count_ptr != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1468, "assert(" "java_fields_count_ptr != __null" ") failed" , "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
1469 | |||||||||||||
1470 | assert(NULL == _fields, "invariant")do { if (!(__null == _fields)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1470, "assert(" "__null == _fields" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
1471 | assert(NULL == _fields_annotations, "invariant")do { if (!(__null == _fields_annotations)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1471, "assert(" "__null == _fields_annotations" ") failed", "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
1472 | assert(NULL == _fields_type_annotations, "invariant")do { if (!(__null == _fields_type_annotations)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1472, "assert(" "__null == _fields_type_annotations" ") failed" , "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
1473 | |||||||||||||
1474 | cfs->guarantee_more(2, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // length | ||||||||||||
1475 | const u2 length = cfs->get_u2_fast(); | ||||||||||||
1476 | *java_fields_count_ptr = length; | ||||||||||||
1477 | |||||||||||||
1478 | int num_injected = 0; | ||||||||||||
1479 | const InjectedField* const injected = JavaClasses::get_injected(_class_name, | ||||||||||||
1480 | &num_injected); | ||||||||||||
1481 | const int total_fields = length + num_injected; | ||||||||||||
1482 | |||||||||||||
1483 | // The field array starts with tuples of shorts | ||||||||||||
1484 | // [access, name index, sig index, initial value index, byte offset]. | ||||||||||||
1485 | // A generic signature slot only exists for field with generic | ||||||||||||
1486 | // signature attribute. And the access flag is set with | ||||||||||||
1487 | // JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE for that field. The generic | ||||||||||||
1488 | // signature slots are at the end of the field array and after all | ||||||||||||
1489 | // other fields data. | ||||||||||||
1490 | // | ||||||||||||
1491 | // f1: [access, name index, sig index, initial value index, low_offset, high_offset] | ||||||||||||
1492 | // f2: [access, name index, sig index, initial value index, low_offset, high_offset] | ||||||||||||
1493 | // ... | ||||||||||||
1494 | // fn: [access, name index, sig index, initial value index, low_offset, high_offset] | ||||||||||||
1495 | // [generic signature index] | ||||||||||||
1496 | // [generic signature index] | ||||||||||||
1497 | // ... | ||||||||||||
1498 | // | ||||||||||||
1499 | // Allocate a temporary resource array for field data. For each field, | ||||||||||||
1500 | // a slot is reserved in the temporary array for the generic signature | ||||||||||||
1501 | // index. After parsing all fields, the data are copied to a permanent | ||||||||||||
1502 | // array and any unused slots will be discarded. | ||||||||||||
1503 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
1504 | u2* const fa = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD,(u2*) resource_allocate_bytes(__the_thread__, (total_fields * (FieldInfo::field_slots + 1)) * sizeof(u2)) | ||||||||||||
1505 | u2,(u2*) resource_allocate_bytes(__the_thread__, (total_fields * (FieldInfo::field_slots + 1)) * sizeof(u2)) | ||||||||||||
1506 | total_fields * (FieldInfo::field_slots + 1))(u2*) resource_allocate_bytes(__the_thread__, (total_fields * (FieldInfo::field_slots + 1)) * sizeof(u2)); | ||||||||||||
1507 | |||||||||||||
1508 | // The generic signature slots start after all other fields' data. | ||||||||||||
1509 | int generic_signature_slot = total_fields * FieldInfo::field_slots; | ||||||||||||
1510 | int num_generic_signature = 0; | ||||||||||||
1511 | for (int n = 0; n < length; n++) { | ||||||||||||
1512 | // access_flags, name_index, descriptor_index, attributes_count | ||||||||||||
1513 | cfs->guarantee_more(8, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1514 | |||||||||||||
1515 | AccessFlags access_flags; | ||||||||||||
1516 | const jint flags = cfs->get_u2_fast() & JVM_RECOGNIZED_FIELD_MODIFIERS(JVM_ACC_PUBLIC | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC | JVM_ACC_FINAL | JVM_ACC_VOLATILE | JVM_ACC_TRANSIENT | JVM_ACC_ENUM | JVM_ACC_SYNTHETIC); | ||||||||||||
1517 | verify_legal_field_modifiers(flags, is_interface, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1518 | access_flags.set_flags(flags); | ||||||||||||
1519 | |||||||||||||
1520 | const u2 name_index = cfs->get_u2_fast(); | ||||||||||||
1521 | check_property(valid_symbol_at(name_index), | ||||||||||||
1522 | "Invalid constant pool index %u for field name in class file %s", | ||||||||||||
1523 | name_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1524 | const Symbol* const name = cp->symbol_at(name_index); | ||||||||||||
1525 | verify_legal_field_name(name, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1526 | |||||||||||||
1527 | const u2 signature_index = cfs->get_u2_fast(); | ||||||||||||
1528 | check_property(valid_symbol_at(signature_index), | ||||||||||||
1529 | "Invalid constant pool index %u for field signature in class file %s", | ||||||||||||
1530 | signature_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1531 | const Symbol* const sig = cp->symbol_at(signature_index); | ||||||||||||
1532 | verify_legal_field_signature(name, sig, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1533 | |||||||||||||
1534 | u2 constantvalue_index = 0; | ||||||||||||
1535 | bool is_synthetic = false; | ||||||||||||
1536 | u2 generic_signature_index = 0; | ||||||||||||
1537 | const bool is_static = access_flags.is_static(); | ||||||||||||
1538 | FieldAnnotationCollector parsed_annotations(_loader_data); | ||||||||||||
1539 | |||||||||||||
1540 | const u2 attributes_count = cfs->get_u2_fast(); | ||||||||||||
1541 | if (attributes_count > 0) { | ||||||||||||
1542 | parse_field_attributes(cfs, | ||||||||||||
1543 | attributes_count, | ||||||||||||
1544 | is_static, | ||||||||||||
1545 | signature_index, | ||||||||||||
1546 | &constantvalue_index, | ||||||||||||
1547 | &is_synthetic, | ||||||||||||
1548 | &generic_signature_index, | ||||||||||||
1549 | &parsed_annotations, | ||||||||||||
1550 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1551 | |||||||||||||
1552 | if (parsed_annotations.field_annotations() != NULL__null) { | ||||||||||||
1553 | if (_fields_annotations == NULL__null) { | ||||||||||||
1554 | _fields_annotations = MetadataFactory::new_array<AnnotationArray*>( | ||||||||||||
1555 | _loader_data, length, NULL__null, | ||||||||||||
1556 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1557 | } | ||||||||||||
1558 | _fields_annotations->at_put(n, parsed_annotations.field_annotations()); | ||||||||||||
1559 | parsed_annotations.set_field_annotations(NULL__null); | ||||||||||||
1560 | } | ||||||||||||
1561 | if (parsed_annotations.field_type_annotations() != NULL__null) { | ||||||||||||
1562 | if (_fields_type_annotations == NULL__null) { | ||||||||||||
1563 | _fields_type_annotations = | ||||||||||||
1564 | MetadataFactory::new_array<AnnotationArray*>(_loader_data, | ||||||||||||
1565 | length, | ||||||||||||
1566 | NULL__null, | ||||||||||||
1567 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1568 | } | ||||||||||||
1569 | _fields_type_annotations->at_put(n, parsed_annotations.field_type_annotations()); | ||||||||||||
1570 | parsed_annotations.set_field_type_annotations(NULL__null); | ||||||||||||
1571 | } | ||||||||||||
1572 | |||||||||||||
1573 | if (is_synthetic) { | ||||||||||||
1574 | access_flags.set_is_synthetic(); | ||||||||||||
1575 | } | ||||||||||||
1576 | if (generic_signature_index != 0) { | ||||||||||||
1577 | access_flags.set_field_has_generic_signature(); | ||||||||||||
1578 | fa[generic_signature_slot] = generic_signature_index; | ||||||||||||
1579 | generic_signature_slot ++; | ||||||||||||
1580 | num_generic_signature ++; | ||||||||||||
1581 | } | ||||||||||||
1582 | } | ||||||||||||
1583 | |||||||||||||
1584 | FieldInfo* const field = FieldInfo::from_field_array(fa, n); | ||||||||||||
1585 | field->initialize(access_flags.as_short(), | ||||||||||||
1586 | name_index, | ||||||||||||
1587 | signature_index, | ||||||||||||
1588 | constantvalue_index); | ||||||||||||
1589 | const BasicType type = cp->basic_type_for_signature_at(signature_index); | ||||||||||||
1590 | |||||||||||||
1591 | // Update FieldAllocationCount for this kind of field | ||||||||||||
1592 | fac->update(is_static, type); | ||||||||||||
1593 | |||||||||||||
1594 | // After field is initialized with type, we can augment it with aux info | ||||||||||||
1595 | if (parsed_annotations.has_any_annotations()) { | ||||||||||||
1596 | parsed_annotations.apply_to(field); | ||||||||||||
1597 | if (field->is_contended()) { | ||||||||||||
1598 | _has_contended_fields = true; | ||||||||||||
1599 | } | ||||||||||||
1600 | } | ||||||||||||
1601 | } | ||||||||||||
1602 | |||||||||||||
1603 | int index = length; | ||||||||||||
1604 | if (num_injected != 0) { | ||||||||||||
1605 | for (int n = 0; n < num_injected; n++) { | ||||||||||||
1606 | // Check for duplicates | ||||||||||||
1607 | if (injected[n].may_be_java) { | ||||||||||||
1608 | const Symbol* const name = injected[n].name(); | ||||||||||||
1609 | const Symbol* const signature = injected[n].signature(); | ||||||||||||
1610 | bool duplicate = false; | ||||||||||||
1611 | for (int i = 0; i < length; i++) { | ||||||||||||
1612 | const FieldInfo* const f = FieldInfo::from_field_array(fa, i); | ||||||||||||
1613 | if (name == cp->symbol_at(f->name_index()) && | ||||||||||||
1614 | signature == cp->symbol_at(f->signature_index())) { | ||||||||||||
1615 | // Symbol is desclared in Java so skip this one | ||||||||||||
1616 | duplicate = true; | ||||||||||||
1617 | break; | ||||||||||||
1618 | } | ||||||||||||
1619 | } | ||||||||||||
1620 | if (duplicate) { | ||||||||||||
1621 | // These will be removed from the field array at the end | ||||||||||||
1622 | continue; | ||||||||||||
1623 | } | ||||||||||||
1624 | } | ||||||||||||
1625 | |||||||||||||
1626 | // Injected field | ||||||||||||
1627 | FieldInfo* const field = FieldInfo::from_field_array(fa, index); | ||||||||||||
1628 | field->initialize((u2)JVM_ACC_FIELD_INTERNAL, | ||||||||||||
1629 | (u2)(injected[n].name_index), | ||||||||||||
1630 | (u2)(injected[n].signature_index), | ||||||||||||
1631 | 0); | ||||||||||||
1632 | |||||||||||||
1633 | const BasicType type = Signature::basic_type(injected[n].signature()); | ||||||||||||
1634 | |||||||||||||
1635 | // Update FieldAllocationCount for this kind of field | ||||||||||||
1636 | fac->update(false, type); | ||||||||||||
1637 | index++; | ||||||||||||
1638 | } | ||||||||||||
1639 | } | ||||||||||||
1640 | |||||||||||||
1641 | assert(NULL == _fields, "invariant")do { if (!(__null == _fields)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1641, "assert(" "__null == _fields" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
1642 | |||||||||||||
1643 | _fields = | ||||||||||||
1644 | MetadataFactory::new_array<u2>(_loader_data, | ||||||||||||
1645 | index * FieldInfo::field_slots + num_generic_signature, | ||||||||||||
1646 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1647 | // Sometimes injected fields already exist in the Java source so | ||||||||||||
1648 | // the fields array could be too long. In that case the | ||||||||||||
1649 | // fields array is trimed. Also unused slots that were reserved | ||||||||||||
1650 | // for generic signature indexes are discarded. | ||||||||||||
1651 | { | ||||||||||||
1652 | int i = 0; | ||||||||||||
1653 | for (; i < index * FieldInfo::field_slots; i++) { | ||||||||||||
1654 | _fields->at_put(i, fa[i]); | ||||||||||||
1655 | } | ||||||||||||
1656 | for (int j = total_fields * FieldInfo::field_slots; | ||||||||||||
1657 | j < generic_signature_slot; j++) { | ||||||||||||
1658 | _fields->at_put(i++, fa[j]); | ||||||||||||
1659 | } | ||||||||||||
1660 | assert(_fields->length() == i, "")do { if (!(_fields->length() == i)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1660, "assert(" "_fields->length() == i" ") failed", "") ; ::breakpoint(); } } while (0); | ||||||||||||
1661 | } | ||||||||||||
1662 | |||||||||||||
1663 | if (_need_verify && length > 1) { | ||||||||||||
1664 | // Check duplicated fields | ||||||||||||
1665 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
1666 | NameSigHash** names_and_sigs = NEW_RESOURCE_ARRAY_IN_THREAD((NameSigHash**) resource_allocate_bytes(__the_thread__, (HASH_ROW_SIZE ) * sizeof(NameSigHash*)) | ||||||||||||
1667 | THREAD, NameSigHash*, HASH_ROW_SIZE)(NameSigHash**) resource_allocate_bytes(__the_thread__, (HASH_ROW_SIZE ) * sizeof(NameSigHash*)); | ||||||||||||
1668 | initialize_hashtable(names_and_sigs); | ||||||||||||
1669 | bool dup = false; | ||||||||||||
1670 | const Symbol* name = NULL__null; | ||||||||||||
1671 | const Symbol* sig = NULL__null; | ||||||||||||
1672 | { | ||||||||||||
1673 | debug_only(NoSafepointVerifier nsv;)NoSafepointVerifier nsv; | ||||||||||||
1674 | for (AllFieldStream fs(_fields, cp); !fs.done(); fs.next()) { | ||||||||||||
1675 | name = fs.name(); | ||||||||||||
1676 | sig = fs.signature(); | ||||||||||||
1677 | // If no duplicates, add name/signature in hashtable names_and_sigs. | ||||||||||||
1678 | if (!put_after_lookup(name, sig, names_and_sigs)) { | ||||||||||||
1679 | dup = true; | ||||||||||||
1680 | break; | ||||||||||||
1681 | } | ||||||||||||
1682 | } | ||||||||||||
1683 | } | ||||||||||||
1684 | if (dup) { | ||||||||||||
1685 | classfile_parse_error("Duplicate field name \"%s\" with signature \"%s\" in class file %s", | ||||||||||||
1686 | name->as_C_string(), sig->as_klass_external_name(), THREAD__the_thread__); | ||||||||||||
1687 | } | ||||||||||||
1688 | } | ||||||||||||
1689 | } | ||||||||||||
1690 | |||||||||||||
1691 | |||||||||||||
1692 | const ClassFileParser::unsafe_u2* ClassFileParser::parse_exception_table(const ClassFileStream* const cfs, | ||||||||||||
1693 | u4 code_length, | ||||||||||||
1694 | u4 exception_table_length, | ||||||||||||
1695 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
1696 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1696, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
1697 | |||||||||||||
1698 | const unsafe_u2* const exception_table_start = cfs->current(); | ||||||||||||
1699 | assert(exception_table_start != NULL, "null exception table")do { if (!(exception_table_start != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1699, "assert(" "exception_table_start != __null" ") failed" , "null exception table"); ::breakpoint(); } } while (0); | ||||||||||||
1700 | |||||||||||||
1701 | cfs->guarantee_more(8 * exception_table_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); // start_pc, | ||||||||||||
1702 | // end_pc, | ||||||||||||
1703 | // handler_pc, | ||||||||||||
1704 | // catch_type_index | ||||||||||||
1705 | |||||||||||||
1706 | // Will check legal target after parsing code array in verifier. | ||||||||||||
1707 | if (_need_verify) { | ||||||||||||
1708 | for (unsigned int i = 0; i < exception_table_length; i++) { | ||||||||||||
1709 | const u2 start_pc = cfs->get_u2_fast(); | ||||||||||||
1710 | const u2 end_pc = cfs->get_u2_fast(); | ||||||||||||
1711 | const u2 handler_pc = cfs->get_u2_fast(); | ||||||||||||
1712 | const u2 catch_type_index = cfs->get_u2_fast(); | ||||||||||||
1713 | guarantee_property((start_pc < end_pc) && (end_pc <= code_length), | ||||||||||||
1714 | "Illegal exception table range in class file %s", | ||||||||||||
1715 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
1716 | guarantee_property(handler_pc < code_length, | ||||||||||||
1717 | "Illegal exception table handler in class file %s", | ||||||||||||
1718 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
1719 | if (catch_type_index != 0) { | ||||||||||||
1720 | guarantee_property(valid_klass_reference_at(catch_type_index), | ||||||||||||
1721 | "Catch type in exception table has bad constant type in class file %s", CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
1722 | } | ||||||||||||
1723 | } | ||||||||||||
1724 | } else { | ||||||||||||
1725 | cfs->skip_u2_fast(exception_table_length * 4); | ||||||||||||
1726 | } | ||||||||||||
1727 | return exception_table_start; | ||||||||||||
1728 | } | ||||||||||||
1729 | |||||||||||||
1730 | void ClassFileParser::parse_linenumber_table(u4 code_attribute_length, | ||||||||||||
1731 | u4 code_length, | ||||||||||||
1732 | CompressedLineNumberWriteStream**const write_stream, | ||||||||||||
1733 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
1734 | |||||||||||||
1735 | const ClassFileStream* const cfs = _stream; | ||||||||||||
1736 | unsigned int num_entries = cfs->get_u2(CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1737 | |||||||||||||
1738 | // Each entry is a u2 start_pc, and a u2 line_number | ||||||||||||
1739 | const unsigned int length_in_bytes = num_entries * (sizeof(u2) * 2); | ||||||||||||
1740 | |||||||||||||
1741 | // Verify line number attribute and table length | ||||||||||||
1742 | check_property( | ||||||||||||
1743 | code_attribute_length == sizeof(u2) + length_in_bytes, | ||||||||||||
1744 | "LineNumberTable attribute has wrong length in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1745 | |||||||||||||
1746 | cfs->guarantee_more(length_in_bytes, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1747 | |||||||||||||
1748 | if ((*write_stream) == NULL__null) { | ||||||||||||
1749 | if (length_in_bytes > fixed_buffer_size) { | ||||||||||||
1750 | (*write_stream) = new CompressedLineNumberWriteStream(length_in_bytes); | ||||||||||||
1751 | } else { | ||||||||||||
1752 | (*write_stream) = new CompressedLineNumberWriteStream( | ||||||||||||
1753 | _linenumbertable_buffer, fixed_buffer_size); | ||||||||||||
1754 | } | ||||||||||||
1755 | } | ||||||||||||
1756 | |||||||||||||
1757 | while (num_entries-- > 0) { | ||||||||||||
1758 | const u2 bci = cfs->get_u2_fast(); // start_pc | ||||||||||||
1759 | const u2 line = cfs->get_u2_fast(); // line_number | ||||||||||||
1760 | guarantee_property(bci < code_length, | ||||||||||||
1761 | "Invalid pc in LineNumberTable in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
1762 | (*write_stream)->write_pair(bci, line); | ||||||||||||
1763 | } | ||||||||||||
1764 | } | ||||||||||||
1765 | |||||||||||||
1766 | |||||||||||||
1767 | class LVT_Hash : public AllStatic { | ||||||||||||
1768 | public: | ||||||||||||
1769 | |||||||||||||
1770 | static bool equals(LocalVariableTableElement const& e0, LocalVariableTableElement const& e1) { | ||||||||||||
1771 | /* | ||||||||||||
1772 | * 3-tuple start_bci/length/slot has to be unique key, | ||||||||||||
1773 | * so the following comparison seems to be redundant: | ||||||||||||
1774 | * && elem->name_cp_index == entry->_elem->name_cp_index | ||||||||||||
1775 | */ | ||||||||||||
1776 | return (e0.start_bci == e1.start_bci && | ||||||||||||
1777 | e0.length == e1.length && | ||||||||||||
1778 | e0.name_cp_index == e1.name_cp_index && | ||||||||||||
1779 | e0.slot == e1.slot); | ||||||||||||
1780 | } | ||||||||||||
1781 | |||||||||||||
1782 | static unsigned int hash(LocalVariableTableElement const& e0) { | ||||||||||||
1783 | unsigned int raw_hash = e0.start_bci; | ||||||||||||
1784 | |||||||||||||
1785 | raw_hash = e0.length + raw_hash * 37; | ||||||||||||
1786 | raw_hash = e0.name_cp_index + raw_hash * 37; | ||||||||||||
1787 | raw_hash = e0.slot + raw_hash * 37; | ||||||||||||
1788 | |||||||||||||
1789 | return raw_hash; | ||||||||||||
1790 | } | ||||||||||||
1791 | }; | ||||||||||||
1792 | |||||||||||||
1793 | |||||||||||||
1794 | // Class file LocalVariableTable elements. | ||||||||||||
1795 | class Classfile_LVT_Element { | ||||||||||||
1796 | public: | ||||||||||||
1797 | u2 start_bci; | ||||||||||||
1798 | u2 length; | ||||||||||||
1799 | u2 name_cp_index; | ||||||||||||
1800 | u2 descriptor_cp_index; | ||||||||||||
1801 | u2 slot; | ||||||||||||
1802 | }; | ||||||||||||
1803 | |||||||||||||
1804 | static void copy_lvt_element(const Classfile_LVT_Element* const src, | ||||||||||||
1805 | LocalVariableTableElement* const lvt) { | ||||||||||||
1806 | lvt->start_bci = Bytes::get_Java_u2((u1*) &src->start_bci); | ||||||||||||
1807 | lvt->length = Bytes::get_Java_u2((u1*) &src->length); | ||||||||||||
1808 | lvt->name_cp_index = Bytes::get_Java_u2((u1*) &src->name_cp_index); | ||||||||||||
1809 | lvt->descriptor_cp_index = Bytes::get_Java_u2((u1*) &src->descriptor_cp_index); | ||||||||||||
1810 | lvt->signature_cp_index = 0; | ||||||||||||
1811 | lvt->slot = Bytes::get_Java_u2((u1*) &src->slot); | ||||||||||||
1812 | } | ||||||||||||
1813 | |||||||||||||
1814 | // Function is used to parse both attributes: | ||||||||||||
1815 | // LocalVariableTable (LVT) and LocalVariableTypeTable (LVTT) | ||||||||||||
1816 | const ClassFileParser::unsafe_u2* ClassFileParser::parse_localvariable_table(const ClassFileStream* cfs, | ||||||||||||
1817 | u4 code_length, | ||||||||||||
1818 | u2 max_locals, | ||||||||||||
1819 | u4 code_attribute_length, | ||||||||||||
1820 | u2* const localvariable_table_length, | ||||||||||||
1821 | bool isLVTT, | ||||||||||||
1822 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
1823 | const char* const tbl_name = (isLVTT) ? "LocalVariableTypeTable" : "LocalVariableTable"; | ||||||||||||
1824 | *localvariable_table_length = cfs->get_u2(CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
1825 | const unsigned int size = | ||||||||||||
1826 | (*localvariable_table_length) * sizeof(Classfile_LVT_Element) / sizeof(u2); | ||||||||||||
1827 | |||||||||||||
1828 | const ConstantPool* const cp = _cp; | ||||||||||||
1829 | |||||||||||||
1830 | // Verify local variable table attribute has right length | ||||||||||||
1831 | if (_need_verify) { | ||||||||||||
1832 | guarantee_property(code_attribute_length == (sizeof(*localvariable_table_length) + size * sizeof(u2)), | ||||||||||||
1833 | "%s has wrong length in class file %s", tbl_name, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
1834 | } | ||||||||||||
1835 | |||||||||||||
1836 | const unsafe_u2* const localvariable_table_start = cfs->current(); | ||||||||||||
1837 | assert(localvariable_table_start != NULL, "null local variable table")do { if (!(localvariable_table_start != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1837, "assert(" "localvariable_table_start != __null" ") failed" , "null local variable table"); ::breakpoint(); } } while (0); | ||||||||||||
1838 | if (!_need_verify) { | ||||||||||||
1839 | cfs->skip_u2_fast(size); | ||||||||||||
1840 | } else { | ||||||||||||
1841 | cfs->guarantee_more(size * 2, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
1842 | for(int i = 0; i < (*localvariable_table_length); i++) { | ||||||||||||
1843 | const u2 start_pc = cfs->get_u2_fast(); | ||||||||||||
1844 | const u2 length = cfs->get_u2_fast(); | ||||||||||||
1845 | const u2 name_index = cfs->get_u2_fast(); | ||||||||||||
1846 | const u2 descriptor_index = cfs->get_u2_fast(); | ||||||||||||
1847 | const u2 index = cfs->get_u2_fast(); | ||||||||||||
1848 | // Assign to a u4 to avoid overflow | ||||||||||||
1849 | const u4 end_pc = (u4)start_pc + (u4)length; | ||||||||||||
1850 | |||||||||||||
1851 | if (start_pc >= code_length) { | ||||||||||||
1852 | classfile_parse_error( | ||||||||||||
1853 | "Invalid start_pc %u in %s in class file %s", | ||||||||||||
1854 | start_pc, tbl_name, THREAD__the_thread__); | ||||||||||||
1855 | return NULL__null; | ||||||||||||
1856 | } | ||||||||||||
1857 | if (end_pc > code_length) { | ||||||||||||
1858 | classfile_parse_error( | ||||||||||||
1859 | "Invalid length %u in %s in class file %s", | ||||||||||||
1860 | length, tbl_name, THREAD__the_thread__); | ||||||||||||
1861 | return NULL__null; | ||||||||||||
1862 | } | ||||||||||||
1863 | const int cp_size = cp->length(); | ||||||||||||
1864 | guarantee_property(valid_symbol_at(name_index), | ||||||||||||
1865 | "Name index %u in %s has bad constant type in class file %s", | ||||||||||||
1866 | name_index, tbl_name, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
1867 | guarantee_property(valid_symbol_at(descriptor_index), | ||||||||||||
1868 | "Signature index %u in %s has bad constant type in class file %s", | ||||||||||||
1869 | descriptor_index, tbl_name, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
1870 | |||||||||||||
1871 | const Symbol* const name = cp->symbol_at(name_index); | ||||||||||||
1872 | const Symbol* const sig = cp->symbol_at(descriptor_index); | ||||||||||||
1873 | verify_legal_field_name(name, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
1874 | u2 extra_slot = 0; | ||||||||||||
1875 | if (!isLVTT) { | ||||||||||||
1876 | verify_legal_field_signature(name, sig, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
1877 | |||||||||||||
1878 | // 4894874: check special cases for double and long local variables | ||||||||||||
1879 | if (sig == vmSymbols::type_signature(T_DOUBLE) || | ||||||||||||
1880 | sig == vmSymbols::type_signature(T_LONG)) { | ||||||||||||
1881 | extra_slot = 1; | ||||||||||||
1882 | } | ||||||||||||
1883 | } | ||||||||||||
1884 | guarantee_property((index + extra_slot) < max_locals, | ||||||||||||
1885 | "Invalid index %u in %s in class file %s", | ||||||||||||
1886 | index, tbl_name, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
1887 | } | ||||||||||||
1888 | } | ||||||||||||
1889 | return localvariable_table_start; | ||||||||||||
1890 | } | ||||||||||||
1891 | |||||||||||||
1892 | static const u1* parse_stackmap_table(const ClassFileStream* const cfs, | ||||||||||||
1893 | u4 code_attribute_length, | ||||||||||||
1894 | bool need_verify, | ||||||||||||
1895 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
1896 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1896, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
1897 | |||||||||||||
1898 | if (0 == code_attribute_length) { | ||||||||||||
1899 | return NULL__null; | ||||||||||||
1900 | } | ||||||||||||
1901 | |||||||||||||
1902 | const u1* const stackmap_table_start = cfs->current(); | ||||||||||||
1903 | assert(stackmap_table_start != NULL, "null stackmap table")do { if (!(stackmap_table_start != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1903, "assert(" "stackmap_table_start != __null" ") failed" , "null stackmap table"); ::breakpoint(); } } while (0); | ||||||||||||
1904 | |||||||||||||
1905 | // check code_attribute_length first | ||||||||||||
1906 | cfs->skip_u1(code_attribute_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
1907 | |||||||||||||
1908 | if (!need_verify && !DumpSharedSpaces) { | ||||||||||||
1909 | return NULL__null; | ||||||||||||
1910 | } | ||||||||||||
1911 | return stackmap_table_start; | ||||||||||||
1912 | } | ||||||||||||
1913 | |||||||||||||
1914 | const ClassFileParser::unsafe_u2* ClassFileParser::parse_checked_exceptions(const ClassFileStream* const cfs, | ||||||||||||
1915 | u2* const checked_exceptions_length, | ||||||||||||
1916 | u4 method_attribute_length, | ||||||||||||
1917 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
1918 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1918, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
1919 | assert(checked_exceptions_length != NULL, "invariant")do { if (!(checked_exceptions_length != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1919, "assert(" "checked_exceptions_length != __null" ") failed" , "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
1920 | |||||||||||||
1921 | cfs->guarantee_more(2, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); // checked_exceptions_length | ||||||||||||
1922 | *checked_exceptions_length = cfs->get_u2_fast(); | ||||||||||||
1923 | const unsigned int size = | ||||||||||||
1924 | (*checked_exceptions_length) * sizeof(CheckedExceptionElement) / sizeof(u2); | ||||||||||||
1925 | const unsafe_u2* const checked_exceptions_start = cfs->current(); | ||||||||||||
1926 | assert(checked_exceptions_start != NULL, "null checked exceptions")do { if (!(checked_exceptions_start != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1926, "assert(" "checked_exceptions_start != __null" ") failed" , "null checked exceptions"); ::breakpoint(); } } while (0); | ||||||||||||
1927 | if (!_need_verify) { | ||||||||||||
1928 | cfs->skip_u2_fast(size); | ||||||||||||
1929 | } else { | ||||||||||||
1930 | // Verify each value in the checked exception table | ||||||||||||
1931 | u2 checked_exception; | ||||||||||||
1932 | const u2 len = *checked_exceptions_length; | ||||||||||||
1933 | cfs->guarantee_more(2 * len, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
1934 | for (int i = 0; i < len; i++) { | ||||||||||||
1935 | checked_exception = cfs->get_u2_fast(); | ||||||||||||
1936 | check_property( | ||||||||||||
1937 | valid_klass_reference_at(checked_exception), | ||||||||||||
1938 | "Exception name has bad type at constant pool %u in class file %s", | ||||||||||||
1939 | checked_exception, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
1940 | } | ||||||||||||
1941 | } | ||||||||||||
1942 | // check exceptions attribute length | ||||||||||||
1943 | if (_need_verify) { | ||||||||||||
1944 | guarantee_property(method_attribute_length == (sizeof(*checked_exceptions_length) + | ||||||||||||
1945 | sizeof(u2) * size), | ||||||||||||
1946 | "Exceptions attribute has wrong length in class file %s", CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
1947 | } | ||||||||||||
1948 | return checked_exceptions_start; | ||||||||||||
1949 | } | ||||||||||||
1950 | |||||||||||||
1951 | void ClassFileParser::throwIllegalSignature(const char* type, | ||||||||||||
1952 | const Symbol* name, | ||||||||||||
1953 | const Symbol* sig, | ||||||||||||
1954 | TRAPSJavaThread* __the_thread__) const { | ||||||||||||
1955 | assert(name != NULL, "invariant")do { if (!(name != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1955, "assert(" "name != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
1956 | assert(sig != NULL, "invariant")do { if (!(sig != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1956, "assert(" "sig != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
1957 | |||||||||||||
1958 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
1959 | Exceptions::fthrow(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 1959, | ||||||||||||
1960 | vmSymbols::java_lang_ClassFormatError(), | ||||||||||||
1961 | "%s \"%s\" in class %s has illegal signature \"%s\"", type, | ||||||||||||
1962 | name->as_C_string(), _class_name->as_C_string(), sig->as_C_string()); | ||||||||||||
1963 | } | ||||||||||||
1964 | |||||||||||||
1965 | AnnotationCollector::ID | ||||||||||||
1966 | AnnotationCollector::annotation_index(const ClassLoaderData* loader_data, | ||||||||||||
1967 | const Symbol* name, | ||||||||||||
1968 | const bool can_access_vm_annotations) { | ||||||||||||
1969 | const vmSymbolID sid = vmSymbols::find_sid(name); | ||||||||||||
1970 | // Privileged code can use all annotations. Other code silently drops some. | ||||||||||||
1971 | const bool privileged = loader_data->is_boot_class_loader_data() || | ||||||||||||
1972 | loader_data->is_platform_class_loader_data() || | ||||||||||||
1973 | can_access_vm_annotations; | ||||||||||||
1974 | switch (sid) { | ||||||||||||
1975 | case VM_SYMBOL_ENUM_NAME(reflect_CallerSensitive_signature)vmSymbolID::reflect_CallerSensitive_signature_enum: { | ||||||||||||
1976 | if (_location != _in_method) break; // only allow for methods | ||||||||||||
1977 | if (!privileged) break; // only allow in privileged code | ||||||||||||
1978 | return _method_CallerSensitive; | ||||||||||||
1979 | } | ||||||||||||
1980 | case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_ForceInline_signature)vmSymbolID::jdk_internal_vm_annotation_ForceInline_signature_enum: { | ||||||||||||
1981 | if (_location != _in_method) break; // only allow for methods | ||||||||||||
1982 | if (!privileged) break; // only allow in privileged code | ||||||||||||
1983 | return _method_ForceInline; | ||||||||||||
1984 | } | ||||||||||||
1985 | case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_DontInline_signature)vmSymbolID::jdk_internal_vm_annotation_DontInline_signature_enum: { | ||||||||||||
1986 | if (_location != _in_method) break; // only allow for methods | ||||||||||||
1987 | if (!privileged) break; // only allow in privileged code | ||||||||||||
1988 | return _method_DontInline; | ||||||||||||
1989 | } | ||||||||||||
1990 | case VM_SYMBOL_ENUM_NAME(java_lang_invoke_InjectedProfile_signature)vmSymbolID::java_lang_invoke_InjectedProfile_signature_enum: { | ||||||||||||
1991 | if (_location != _in_method) break; // only allow for methods | ||||||||||||
1992 | if (!privileged) break; // only allow in privileged code | ||||||||||||
1993 | return _method_InjectedProfile; | ||||||||||||
1994 | } | ||||||||||||
1995 | case VM_SYMBOL_ENUM_NAME(java_lang_invoke_LambdaForm_Compiled_signature)vmSymbolID::java_lang_invoke_LambdaForm_Compiled_signature_enum: { | ||||||||||||
1996 | if (_location != _in_method) break; // only allow for methods | ||||||||||||
1997 | if (!privileged) break; // only allow in privileged code | ||||||||||||
1998 | return _method_LambdaForm_Compiled; | ||||||||||||
1999 | } | ||||||||||||
2000 | case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_Hidden_signature)vmSymbolID::jdk_internal_vm_annotation_Hidden_signature_enum: { | ||||||||||||
2001 | if (_location != _in_method) break; // only allow for methods | ||||||||||||
2002 | if (!privileged) break; // only allow in privileged code | ||||||||||||
2003 | return _method_Hidden; | ||||||||||||
2004 | } | ||||||||||||
2005 | case VM_SYMBOL_ENUM_NAME(jdk_internal_misc_Scoped_signature)vmSymbolID::jdk_internal_misc_Scoped_signature_enum: { | ||||||||||||
2006 | if (_location != _in_method) break; // only allow for methods | ||||||||||||
2007 | if (!privileged) break; // only allow in privileged code | ||||||||||||
2008 | return _method_Scoped; | ||||||||||||
2009 | } | ||||||||||||
2010 | case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_IntrinsicCandidate_signature)vmSymbolID::jdk_internal_vm_annotation_IntrinsicCandidate_signature_enum: { | ||||||||||||
2011 | if (_location != _in_method) break; // only allow for methods | ||||||||||||
2012 | if (!privileged) break; // only allow in privileged code | ||||||||||||
2013 | return _method_IntrinsicCandidate; | ||||||||||||
2014 | } | ||||||||||||
2015 | case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_Stable_signature)vmSymbolID::jdk_internal_vm_annotation_Stable_signature_enum: { | ||||||||||||
2016 | if (_location != _in_field) break; // only allow for fields | ||||||||||||
2017 | if (!privileged) break; // only allow in privileged code | ||||||||||||
2018 | return _field_Stable; | ||||||||||||
2019 | } | ||||||||||||
2020 | case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_Contended_signature)vmSymbolID::jdk_internal_vm_annotation_Contended_signature_enum: { | ||||||||||||
2021 | if (_location != _in_field && _location != _in_class) { | ||||||||||||
2022 | break; // only allow for fields and classes | ||||||||||||
2023 | } | ||||||||||||
2024 | if (!EnableContended || (RestrictContended && !privileged)) { | ||||||||||||
2025 | break; // honor privileges | ||||||||||||
2026 | } | ||||||||||||
2027 | return _jdk_internal_vm_annotation_Contended; | ||||||||||||
2028 | } | ||||||||||||
2029 | case VM_SYMBOL_ENUM_NAME(jdk_internal_vm_annotation_ReservedStackAccess_signature)vmSymbolID::jdk_internal_vm_annotation_ReservedStackAccess_signature_enum: { | ||||||||||||
2030 | if (_location != _in_method) break; // only allow for methods | ||||||||||||
2031 | if (RestrictReservedStack && !privileged) break; // honor privileges | ||||||||||||
2032 | return _jdk_internal_vm_annotation_ReservedStackAccess; | ||||||||||||
2033 | } | ||||||||||||
2034 | case VM_SYMBOL_ENUM_NAME(jdk_internal_ValueBased_signature)vmSymbolID::jdk_internal_ValueBased_signature_enum: { | ||||||||||||
2035 | if (_location != _in_class) break; // only allow for classes | ||||||||||||
2036 | if (!privileged) break; // only allow in priviledged code | ||||||||||||
2037 | return _jdk_internal_ValueBased; | ||||||||||||
2038 | } | ||||||||||||
2039 | default: { | ||||||||||||
2040 | break; | ||||||||||||
2041 | } | ||||||||||||
2042 | } | ||||||||||||
2043 | return AnnotationCollector::_unknown; | ||||||||||||
2044 | } | ||||||||||||
2045 | |||||||||||||
2046 | void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) { | ||||||||||||
2047 | if (is_contended()) | ||||||||||||
2048 | f->set_contended_group(contended_group()); | ||||||||||||
2049 | if (is_stable()) | ||||||||||||
2050 | f->set_stable(true); | ||||||||||||
2051 | } | ||||||||||||
2052 | |||||||||||||
2053 | ClassFileParser::FieldAnnotationCollector::~FieldAnnotationCollector() { | ||||||||||||
2054 | // If there's an error deallocate metadata for field annotations | ||||||||||||
2055 | MetadataFactory::free_array<u1>(_loader_data, _field_annotations); | ||||||||||||
2056 | MetadataFactory::free_array<u1>(_loader_data, _field_type_annotations); | ||||||||||||
2057 | } | ||||||||||||
2058 | |||||||||||||
2059 | void MethodAnnotationCollector::apply_to(const methodHandle& m) { | ||||||||||||
2060 | if (has_annotation(_method_CallerSensitive)) | ||||||||||||
2061 | m->set_caller_sensitive(true); | ||||||||||||
2062 | if (has_annotation(_method_ForceInline)) | ||||||||||||
2063 | m->set_force_inline(true); | ||||||||||||
2064 | if (has_annotation(_method_DontInline)) | ||||||||||||
2065 | m->set_dont_inline(true); | ||||||||||||
2066 | if (has_annotation(_method_InjectedProfile)) | ||||||||||||
2067 | m->set_has_injected_profile(true); | ||||||||||||
2068 | if (has_annotation(_method_LambdaForm_Compiled) && m->intrinsic_id() == vmIntrinsics::_none) | ||||||||||||
2069 | m->set_intrinsic_id(vmIntrinsics::_compiledLambdaForm); | ||||||||||||
2070 | if (has_annotation(_method_Hidden)) | ||||||||||||
2071 | m->set_hidden(true); | ||||||||||||
2072 | if (has_annotation(_method_Scoped)) | ||||||||||||
2073 | m->set_scoped(true); | ||||||||||||
2074 | if (has_annotation(_method_IntrinsicCandidate) && !m->is_synthetic()) | ||||||||||||
2075 | m->set_intrinsic_candidate(true); | ||||||||||||
2076 | if (has_annotation(_jdk_internal_vm_annotation_ReservedStackAccess)) | ||||||||||||
2077 | m->set_has_reserved_stack_access(true); | ||||||||||||
2078 | } | ||||||||||||
2079 | |||||||||||||
2080 | void ClassFileParser::ClassAnnotationCollector::apply_to(InstanceKlass* ik) { | ||||||||||||
2081 | assert(ik != NULL, "invariant")do { if (!(ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2081, "assert(" "ik != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
2082 | if (has_annotation(_jdk_internal_vm_annotation_Contended)) { | ||||||||||||
2083 | ik->set_is_contended(is_contended()); | ||||||||||||
2084 | } | ||||||||||||
2085 | if (has_annotation(_jdk_internal_ValueBased)) { | ||||||||||||
2086 | ik->set_has_value_based_class_annotation(); | ||||||||||||
2087 | if (DiagnoseSyncOnValueBasedClasses) { | ||||||||||||
2088 | ik->set_is_value_based(); | ||||||||||||
2089 | } | ||||||||||||
2090 | } | ||||||||||||
2091 | } | ||||||||||||
2092 | |||||||||||||
2093 | #define MAX_ARGS_SIZE255 255 | ||||||||||||
2094 | #define MAX_CODE_SIZE65535 65535 | ||||||||||||
2095 | #define INITIAL_MAX_LVT_NUMBER256 256 | ||||||||||||
2096 | |||||||||||||
2097 | /* Copy class file LVT's/LVTT's into the HotSpot internal LVT. | ||||||||||||
2098 | * | ||||||||||||
2099 | * Rules for LVT's and LVTT's are: | ||||||||||||
2100 | * - There can be any number of LVT's and LVTT's. | ||||||||||||
2101 | * - If there are n LVT's, it is the same as if there was just | ||||||||||||
2102 | * one LVT containing all the entries from the n LVT's. | ||||||||||||
2103 | * - There may be no more than one LVT entry per local variable. | ||||||||||||
2104 | * Two LVT entries are 'equal' if these fields are the same: | ||||||||||||
2105 | * start_pc, length, name, slot | ||||||||||||
2106 | * - There may be no more than one LVTT entry per each LVT entry. | ||||||||||||
2107 | * Each LVTT entry has to match some LVT entry. | ||||||||||||
2108 | * - HotSpot internal LVT keeps natural ordering of class file LVT entries. | ||||||||||||
2109 | */ | ||||||||||||
2110 | void ClassFileParser::copy_localvariable_table(const ConstMethod* cm, | ||||||||||||
2111 | int lvt_cnt, | ||||||||||||
2112 | u2* const localvariable_table_length, | ||||||||||||
2113 | const unsafe_u2** const localvariable_table_start, | ||||||||||||
2114 | int lvtt_cnt, | ||||||||||||
2115 | u2* const localvariable_type_table_length, | ||||||||||||
2116 | const unsafe_u2** const localvariable_type_table_start, | ||||||||||||
2117 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
2118 | |||||||||||||
2119 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
2120 | |||||||||||||
2121 | typedef ResourceHashtable<LocalVariableTableElement, LocalVariableTableElement*, | ||||||||||||
2122 | 256, ResourceObj::RESOURCE_AREA, mtInternal, | ||||||||||||
2123 | &LVT_Hash::hash, &LVT_Hash::equals> LVT_HashTable; | ||||||||||||
2124 | |||||||||||||
2125 | LVT_HashTable* const table = new LVT_HashTable(); | ||||||||||||
2126 | |||||||||||||
2127 | // To fill LocalVariableTable in | ||||||||||||
2128 | const Classfile_LVT_Element* cf_lvt; | ||||||||||||
2129 | LocalVariableTableElement* lvt = cm->localvariable_table_start(); | ||||||||||||
2130 | |||||||||||||
2131 | for (int tbl_no = 0; tbl_no < lvt_cnt; tbl_no++) { | ||||||||||||
2132 | cf_lvt = (Classfile_LVT_Element *) localvariable_table_start[tbl_no]; | ||||||||||||
2133 | for (int idx = 0; idx < localvariable_table_length[tbl_no]; idx++, lvt++) { | ||||||||||||
2134 | copy_lvt_element(&cf_lvt[idx], lvt); | ||||||||||||
2135 | // If no duplicates, add LVT elem in hashtable. | ||||||||||||
2136 | if (table->put(*lvt, lvt) == false | ||||||||||||
2137 | && _need_verify | ||||||||||||
2138 | && _major_version >= JAVA_1_5_VERSION49) { | ||||||||||||
2139 | classfile_parse_error("Duplicated LocalVariableTable attribute " | ||||||||||||
2140 | "entry for '%s' in class file %s", | ||||||||||||
2141 | _cp->symbol_at(lvt->name_cp_index)->as_utf8(), | ||||||||||||
2142 | THREAD__the_thread__); | ||||||||||||
2143 | return; | ||||||||||||
2144 | } | ||||||||||||
2145 | } | ||||||||||||
2146 | } | ||||||||||||
2147 | |||||||||||||
2148 | // To merge LocalVariableTable and LocalVariableTypeTable | ||||||||||||
2149 | const Classfile_LVT_Element* cf_lvtt; | ||||||||||||
2150 | LocalVariableTableElement lvtt_elem; | ||||||||||||
2151 | |||||||||||||
2152 | for (int tbl_no = 0; tbl_no < lvtt_cnt; tbl_no++) { | ||||||||||||
2153 | cf_lvtt = (Classfile_LVT_Element *) localvariable_type_table_start[tbl_no]; | ||||||||||||
2154 | for (int idx = 0; idx < localvariable_type_table_length[tbl_no]; idx++) { | ||||||||||||
2155 | copy_lvt_element(&cf_lvtt[idx], &lvtt_elem); | ||||||||||||
2156 | LocalVariableTableElement** entry = table->get(lvtt_elem); | ||||||||||||
2157 | if (entry == NULL__null) { | ||||||||||||
2158 | if (_need_verify) { | ||||||||||||
2159 | classfile_parse_error("LVTT entry for '%s' in class file %s " | ||||||||||||
2160 | "does not match any LVT entry", | ||||||||||||
2161 | _cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(), | ||||||||||||
2162 | THREAD__the_thread__); | ||||||||||||
2163 | return; | ||||||||||||
2164 | } | ||||||||||||
2165 | } else if ((*entry)->signature_cp_index != 0 && _need_verify) { | ||||||||||||
2166 | classfile_parse_error("Duplicated LocalVariableTypeTable attribute " | ||||||||||||
2167 | "entry for '%s' in class file %s", | ||||||||||||
2168 | _cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(), | ||||||||||||
2169 | THREAD__the_thread__); | ||||||||||||
2170 | return; | ||||||||||||
2171 | } else { | ||||||||||||
2172 | // to add generic signatures into LocalVariableTable | ||||||||||||
2173 | (*entry)->signature_cp_index = lvtt_elem.descriptor_cp_index; | ||||||||||||
2174 | } | ||||||||||||
2175 | } | ||||||||||||
2176 | } | ||||||||||||
2177 | } | ||||||||||||
2178 | |||||||||||||
2179 | |||||||||||||
2180 | void ClassFileParser::copy_method_annotations(ConstMethod* cm, | ||||||||||||
2181 | const u1* runtime_visible_annotations, | ||||||||||||
2182 | int runtime_visible_annotations_length, | ||||||||||||
2183 | const u1* runtime_invisible_annotations, | ||||||||||||
2184 | int runtime_invisible_annotations_length, | ||||||||||||
2185 | const u1* runtime_visible_parameter_annotations, | ||||||||||||
2186 | int runtime_visible_parameter_annotations_length, | ||||||||||||
2187 | const u1* runtime_invisible_parameter_annotations, | ||||||||||||
2188 | int runtime_invisible_parameter_annotations_length, | ||||||||||||
2189 | const u1* runtime_visible_type_annotations, | ||||||||||||
2190 | int runtime_visible_type_annotations_length, | ||||||||||||
2191 | const u1* runtime_invisible_type_annotations, | ||||||||||||
2192 | int runtime_invisible_type_annotations_length, | ||||||||||||
2193 | const u1* annotation_default, | ||||||||||||
2194 | int annotation_default_length, | ||||||||||||
2195 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
2196 | |||||||||||||
2197 | AnnotationArray* a; | ||||||||||||
2198 | |||||||||||||
2199 | if (runtime_visible_annotations_length + | ||||||||||||
2200 | runtime_invisible_annotations_length > 0) { | ||||||||||||
2201 | a = assemble_annotations(runtime_visible_annotations, | ||||||||||||
2202 | runtime_visible_annotations_length, | ||||||||||||
2203 | runtime_invisible_annotations, | ||||||||||||
2204 | runtime_invisible_annotations_length, | ||||||||||||
2205 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
2206 | cm->set_method_annotations(a); | ||||||||||||
2207 | } | ||||||||||||
2208 | |||||||||||||
2209 | if (runtime_visible_parameter_annotations_length + | ||||||||||||
2210 | runtime_invisible_parameter_annotations_length > 0) { | ||||||||||||
2211 | a = assemble_annotations(runtime_visible_parameter_annotations, | ||||||||||||
2212 | runtime_visible_parameter_annotations_length, | ||||||||||||
2213 | runtime_invisible_parameter_annotations, | ||||||||||||
2214 | runtime_invisible_parameter_annotations_length, | ||||||||||||
2215 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
2216 | cm->set_parameter_annotations(a); | ||||||||||||
2217 | } | ||||||||||||
2218 | |||||||||||||
2219 | if (annotation_default_length > 0) { | ||||||||||||
2220 | a = assemble_annotations(annotation_default, | ||||||||||||
2221 | annotation_default_length, | ||||||||||||
2222 | NULL__null, | ||||||||||||
2223 | 0, | ||||||||||||
2224 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
2225 | cm->set_default_annotations(a); | ||||||||||||
2226 | } | ||||||||||||
2227 | |||||||||||||
2228 | if (runtime_visible_type_annotations_length + | ||||||||||||
2229 | runtime_invisible_type_annotations_length > 0) { | ||||||||||||
2230 | a = assemble_annotations(runtime_visible_type_annotations, | ||||||||||||
2231 | runtime_visible_type_annotations_length, | ||||||||||||
2232 | runtime_invisible_type_annotations, | ||||||||||||
2233 | runtime_invisible_type_annotations_length, | ||||||||||||
2234 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
2235 | cm->set_type_annotations(a); | ||||||||||||
2236 | } | ||||||||||||
2237 | } | ||||||||||||
2238 | |||||||||||||
2239 | |||||||||||||
2240 | // Note: the parse_method below is big and clunky because all parsing of the code and exceptions | ||||||||||||
2241 | // attribute is inlined. This is cumbersome to avoid since we inline most of the parts in the | ||||||||||||
2242 | // Method* to save footprint, so we only know the size of the resulting Method* when the | ||||||||||||
2243 | // entire method attribute is parsed. | ||||||||||||
2244 | // | ||||||||||||
2245 | // The promoted_flags parameter is used to pass relevant access_flags | ||||||||||||
2246 | // from the method back up to the containing klass. These flag values | ||||||||||||
2247 | // are added to klass's access_flags. | ||||||||||||
2248 | |||||||||||||
2249 | Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, | ||||||||||||
2250 | bool is_interface, | ||||||||||||
2251 | const ConstantPool* cp, | ||||||||||||
2252 | AccessFlags* const promoted_flags, | ||||||||||||
2253 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
2254 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2254, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
| |||||||||||||
2255 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2255, "assert(" "cp != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
2256 | assert(promoted_flags != NULL, "invariant")do { if (!(promoted_flags != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2256, "assert(" "promoted_flags != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
2257 | |||||||||||||
2258 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
2259 | // Parse fixed parts: | ||||||||||||
2260 | // access_flags, name_index, descriptor_index, attributes_count | ||||||||||||
2261 | cfs->guarantee_more(8, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2262 | |||||||||||||
2263 | int flags = cfs->get_u2_fast(); | ||||||||||||
2264 | const u2 name_index = cfs->get_u2_fast(); | ||||||||||||
2265 | const int cp_size = cp->length(); | ||||||||||||
2266 | check_property( | ||||||||||||
2267 | valid_symbol_at(name_index), | ||||||||||||
2268 | "Illegal constant pool index %u for method name in class file %s", | ||||||||||||
2269 | name_index, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2270 | const Symbol* const name = cp->symbol_at(name_index); | ||||||||||||
2271 | verify_legal_method_name(name, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2272 | |||||||||||||
2273 | const u2 signature_index = cfs->get_u2_fast(); | ||||||||||||
2274 | guarantee_property( | ||||||||||||
2275 | valid_symbol_at(signature_index), | ||||||||||||
2276 | "Illegal constant pool index %u for method signature in class file %s", | ||||||||||||
2277 | signature_index, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2278 | const Symbol* const signature = cp->symbol_at(signature_index); | ||||||||||||
2279 | |||||||||||||
2280 | if (name == vmSymbols::class_initializer_name()) { | ||||||||||||
2281 | // We ignore the other access flags for a valid class initializer. | ||||||||||||
2282 | // (JVM Spec 2nd ed., chapter 4.6) | ||||||||||||
2283 | if (_major_version < 51) { // backward compatibility | ||||||||||||
2284 | flags = JVM_ACC_STATIC; | ||||||||||||
2285 | } else if ((flags & JVM_ACC_STATIC) == JVM_ACC_STATIC) { | ||||||||||||
2286 | flags &= JVM_ACC_STATIC | (_major_version <= JAVA_16_VERSION60 ? JVM_ACC_STRICT : 0); | ||||||||||||
2287 | } else { | ||||||||||||
2288 | classfile_parse_error("Method <clinit> is not static in class file %s", THREAD__the_thread__); | ||||||||||||
2289 | return NULL__null; | ||||||||||||
2290 | } | ||||||||||||
2291 | } else { | ||||||||||||
2292 | verify_legal_method_modifiers(flags, is_interface, name, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2293 | } | ||||||||||||
2294 | |||||||||||||
2295 | if (name == vmSymbols::object_initializer_name() && is_interface) { | ||||||||||||
2296 | classfile_parse_error("Interface cannot have a method named <init>, class file %s", THREAD__the_thread__); | ||||||||||||
2297 | return NULL__null; | ||||||||||||
2298 | } | ||||||||||||
2299 | |||||||||||||
2300 | int args_size = -1; // only used when _need_verify is true | ||||||||||||
2301 | if (_need_verify
| ||||||||||||
2302 | verify_legal_name_with_signature(name, signature, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2303 | args_size = ((flags & JVM_ACC_STATIC) ? 0 : 1) + | ||||||||||||
2304 | verify_legal_method_signature(name, signature, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2305 | if (args_size
| ||||||||||||
2306 | classfile_parse_error("Too many arguments in method signature in class file %s", THREAD__the_thread__); | ||||||||||||
2307 | return NULL__null; | ||||||||||||
2308 | } | ||||||||||||
2309 | } | ||||||||||||
2310 | |||||||||||||
2311 | AccessFlags access_flags(flags & JVM_RECOGNIZED_METHOD_MODIFIERS(JVM_ACC_PUBLIC | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC | JVM_ACC_FINAL | JVM_ACC_SYNCHRONIZED | JVM_ACC_BRIDGE | JVM_ACC_VARARGS | JVM_ACC_NATIVE | JVM_ACC_ABSTRACT | JVM_ACC_STRICT | JVM_ACC_SYNTHETIC )); | ||||||||||||
2312 | |||||||||||||
2313 | // Default values for code and exceptions attribute elements | ||||||||||||
2314 | u2 max_stack = 0; | ||||||||||||
2315 | u2 max_locals = 0; | ||||||||||||
2316 | u4 code_length = 0; | ||||||||||||
2317 | const u1* code_start = 0; | ||||||||||||
2318 | u2 exception_table_length = 0; | ||||||||||||
2319 | const unsafe_u2* exception_table_start = NULL__null; // (potentially unaligned) pointer to array of u2 elements | ||||||||||||
2320 | Array<int>* exception_handlers = Universe::the_empty_int_array(); | ||||||||||||
2321 | u2 checked_exceptions_length = 0; | ||||||||||||
2322 | const unsafe_u2* checked_exceptions_start = NULL__null; // (potentially unaligned) pointer to array of u2 elements | ||||||||||||
2323 | CompressedLineNumberWriteStream* linenumber_table = NULL__null; | ||||||||||||
2324 | int linenumber_table_length = 0; | ||||||||||||
2325 | int total_lvt_length = 0; | ||||||||||||
2326 | u2 lvt_cnt = 0; | ||||||||||||
2327 | u2 lvtt_cnt = 0; | ||||||||||||
2328 | bool lvt_allocated = false; | ||||||||||||
2329 | u2 max_lvt_cnt = INITIAL_MAX_LVT_NUMBER256; | ||||||||||||
2330 | u2 max_lvtt_cnt = INITIAL_MAX_LVT_NUMBER256; | ||||||||||||
2331 | u2* localvariable_table_length = NULL__null; | ||||||||||||
2332 | const unsafe_u2** localvariable_table_start = NULL__null; // (potentially unaligned) pointer to array of LVT attributes | ||||||||||||
2333 | u2* localvariable_type_table_length = NULL__null; | ||||||||||||
2334 | const unsafe_u2** localvariable_type_table_start = NULL__null; // (potentially unaligned) pointer to LVTT attributes | ||||||||||||
2335 | int method_parameters_length = -1; | ||||||||||||
2336 | const u1* method_parameters_data = NULL__null; | ||||||||||||
2337 | bool method_parameters_seen = false; | ||||||||||||
2338 | bool parsed_code_attribute = false; | ||||||||||||
2339 | bool parsed_checked_exceptions_attribute = false; | ||||||||||||
2340 | bool parsed_stackmap_attribute = false; | ||||||||||||
2341 | // stackmap attribute - JDK1.5 | ||||||||||||
2342 | const u1* stackmap_data = NULL__null; | ||||||||||||
2343 | int stackmap_data_length = 0; | ||||||||||||
2344 | u2 generic_signature_index = 0; | ||||||||||||
2345 | MethodAnnotationCollector parsed_annotations; | ||||||||||||
2346 | const u1* runtime_visible_annotations = NULL__null; | ||||||||||||
2347 | int runtime_visible_annotations_length = 0; | ||||||||||||
2348 | const u1* runtime_invisible_annotations = NULL__null; | ||||||||||||
2349 | int runtime_invisible_annotations_length = 0; | ||||||||||||
2350 | const u1* runtime_visible_parameter_annotations = NULL__null; | ||||||||||||
2351 | int runtime_visible_parameter_annotations_length = 0; | ||||||||||||
2352 | const u1* runtime_invisible_parameter_annotations = NULL__null; | ||||||||||||
2353 | int runtime_invisible_parameter_annotations_length = 0; | ||||||||||||
2354 | const u1* runtime_visible_type_annotations = NULL__null; | ||||||||||||
2355 | int runtime_visible_type_annotations_length = 0; | ||||||||||||
2356 | const u1* runtime_invisible_type_annotations = NULL__null; | ||||||||||||
2357 | int runtime_invisible_type_annotations_length = 0; | ||||||||||||
2358 | bool runtime_invisible_annotations_exists = false; | ||||||||||||
2359 | bool runtime_invisible_type_annotations_exists = false; | ||||||||||||
2360 | bool runtime_invisible_parameter_annotations_exists = false; | ||||||||||||
2361 | const u1* annotation_default = NULL__null; | ||||||||||||
2362 | int annotation_default_length = 0; | ||||||||||||
2363 | |||||||||||||
2364 | // Parse code and exceptions attribute | ||||||||||||
2365 | u2 method_attributes_count = cfs->get_u2_fast(); | ||||||||||||
2366 | while (method_attributes_count--) { | ||||||||||||
2367 | cfs->guarantee_more(6, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); // method_attribute_name_index, method_attribute_length | ||||||||||||
2368 | const u2 method_attribute_name_index = cfs->get_u2_fast(); | ||||||||||||
2369 | const u4 method_attribute_length = cfs->get_u4_fast(); | ||||||||||||
2370 | check_property( | ||||||||||||
2371 | valid_symbol_at(method_attribute_name_index), | ||||||||||||
2372 | "Invalid method attribute name index %u in class file %s", | ||||||||||||
2373 | method_attribute_name_index, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2374 | |||||||||||||
2375 | const Symbol* const method_attribute_name = cp->symbol_at(method_attribute_name_index); | ||||||||||||
2376 | if (method_attribute_name == vmSymbols::tag_code()) { | ||||||||||||
2377 | // Parse Code attribute | ||||||||||||
2378 | if (_need_verify) { | ||||||||||||
2379 | guarantee_property( | ||||||||||||
2380 | !access_flags.is_native() && !access_flags.is_abstract(), | ||||||||||||
2381 | "Code attribute in native or abstract methods in class file %s", | ||||||||||||
2382 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2383 | } | ||||||||||||
2384 | if (parsed_code_attribute) { | ||||||||||||
2385 | classfile_parse_error("Multiple Code attributes in class file %s", | ||||||||||||
2386 | THREAD__the_thread__); | ||||||||||||
2387 | return NULL__null; | ||||||||||||
2388 | } | ||||||||||||
2389 | parsed_code_attribute = true; | ||||||||||||
2390 | |||||||||||||
2391 | // Stack size, locals size, and code size | ||||||||||||
2392 | cfs->guarantee_more(8, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2393 | max_stack = cfs->get_u2_fast(); | ||||||||||||
2394 | max_locals = cfs->get_u2_fast(); | ||||||||||||
2395 | code_length = cfs->get_u4_fast(); | ||||||||||||
2396 | if (_need_verify) { | ||||||||||||
2397 | guarantee_property(args_size <= max_locals, | ||||||||||||
2398 | "Arguments can't fit into locals in class file %s", | ||||||||||||
2399 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2400 | guarantee_property(code_length > 0 && code_length <= MAX_CODE_SIZE65535, | ||||||||||||
2401 | "Invalid method Code length %u in class file %s", | ||||||||||||
2402 | code_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2403 | } | ||||||||||||
2404 | // Code pointer | ||||||||||||
2405 | code_start = cfs->current(); | ||||||||||||
2406 | assert(code_start != NULL, "null code start")do { if (!(code_start != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2406, "assert(" "code_start != __null" ") failed", "null code start" ); ::breakpoint(); } } while (0); | ||||||||||||
2407 | cfs->guarantee_more(code_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2408 | cfs->skip_u1_fast(code_length); | ||||||||||||
2409 | |||||||||||||
2410 | // Exception handler table | ||||||||||||
2411 | cfs->guarantee_more(2, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); // exception_table_length | ||||||||||||
2412 | exception_table_length = cfs->get_u2_fast(); | ||||||||||||
2413 | if (exception_table_length > 0) { | ||||||||||||
2414 | exception_table_start = parse_exception_table(cfs, | ||||||||||||
2415 | code_length, | ||||||||||||
2416 | exception_table_length, | ||||||||||||
2417 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2418 | } | ||||||||||||
2419 | |||||||||||||
2420 | // Parse additional attributes in code attribute | ||||||||||||
2421 | cfs->guarantee_more(2, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); // code_attributes_count | ||||||||||||
2422 | u2 code_attributes_count = cfs->get_u2_fast(); | ||||||||||||
2423 | |||||||||||||
2424 | unsigned int calculated_attribute_length = 0; | ||||||||||||
2425 | |||||||||||||
2426 | calculated_attribute_length = | ||||||||||||
2427 | sizeof(max_stack) + sizeof(max_locals) + sizeof(code_length); | ||||||||||||
2428 | calculated_attribute_length += | ||||||||||||
2429 | code_length + | ||||||||||||
2430 | sizeof(exception_table_length) + | ||||||||||||
2431 | sizeof(code_attributes_count) + | ||||||||||||
2432 | exception_table_length * | ||||||||||||
2433 | ( sizeof(u2) + // start_pc | ||||||||||||
2434 | sizeof(u2) + // end_pc | ||||||||||||
2435 | sizeof(u2) + // handler_pc | ||||||||||||
2436 | sizeof(u2) ); // catch_type_index | ||||||||||||
2437 | |||||||||||||
2438 | while (code_attributes_count--) { | ||||||||||||
2439 | cfs->guarantee_more(6, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); // code_attribute_name_index, code_attribute_length | ||||||||||||
2440 | const u2 code_attribute_name_index = cfs->get_u2_fast(); | ||||||||||||
2441 | const u4 code_attribute_length = cfs->get_u4_fast(); | ||||||||||||
2442 | calculated_attribute_length += code_attribute_length + | ||||||||||||
2443 | sizeof(code_attribute_name_index) + | ||||||||||||
2444 | sizeof(code_attribute_length); | ||||||||||||
2445 | check_property(valid_symbol_at(code_attribute_name_index), | ||||||||||||
2446 | "Invalid code attribute name index %u in class file %s", | ||||||||||||
2447 | code_attribute_name_index, | ||||||||||||
2448 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2449 | if (LoadLineNumberTables && | ||||||||||||
2450 | cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_line_number_table()) { | ||||||||||||
2451 | // Parse and compress line number table | ||||||||||||
2452 | parse_linenumber_table(code_attribute_length, | ||||||||||||
2453 | code_length, | ||||||||||||
2454 | &linenumber_table, | ||||||||||||
2455 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2456 | |||||||||||||
2457 | } else if (LoadLocalVariableTables && | ||||||||||||
2458 | cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_table()) { | ||||||||||||
2459 | // Parse local variable table | ||||||||||||
2460 | if (!lvt_allocated) { | ||||||||||||
2461 | localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD((u2*) resource_allocate_bytes(__the_thread__, (256) * sizeof( u2)) | ||||||||||||
2462 | THREAD, u2, INITIAL_MAX_LVT_NUMBER)(u2*) resource_allocate_bytes(__the_thread__, (256) * sizeof( u2)); | ||||||||||||
2463 | localvariable_table_start = NEW_RESOURCE_ARRAY_IN_THREAD((const unsafe_u2**) resource_allocate_bytes(__the_thread__, ( 256) * sizeof(const unsafe_u2*)) | ||||||||||||
2464 | THREAD, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER)(const unsafe_u2**) resource_allocate_bytes(__the_thread__, ( 256) * sizeof(const unsafe_u2*)); | ||||||||||||
2465 | localvariable_type_table_length = NEW_RESOURCE_ARRAY_IN_THREAD((u2*) resource_allocate_bytes(__the_thread__, (256) * sizeof( u2)) | ||||||||||||
2466 | THREAD, u2, INITIAL_MAX_LVT_NUMBER)(u2*) resource_allocate_bytes(__the_thread__, (256) * sizeof( u2)); | ||||||||||||
2467 | localvariable_type_table_start = NEW_RESOURCE_ARRAY_IN_THREAD((const unsafe_u2**) resource_allocate_bytes(__the_thread__, ( 256) * sizeof(const unsafe_u2*)) | ||||||||||||
2468 | THREAD, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER)(const unsafe_u2**) resource_allocate_bytes(__the_thread__, ( 256) * sizeof(const unsafe_u2*)); | ||||||||||||
2469 | lvt_allocated = true; | ||||||||||||
2470 | } | ||||||||||||
2471 | if (lvt_cnt == max_lvt_cnt) { | ||||||||||||
2472 | max_lvt_cnt <<= 1; | ||||||||||||
2473 | localvariable_table_length = REALLOC_RESOURCE_ARRAY(u2, localvariable_table_length, lvt_cnt, max_lvt_cnt)(u2*) resource_reallocate_bytes((char*)(localvariable_table_length ), (lvt_cnt) * sizeof(u2), (max_lvt_cnt) * sizeof(u2)); | ||||||||||||
2474 | localvariable_table_start = REALLOC_RESOURCE_ARRAY(const unsafe_u2*, localvariable_table_start, lvt_cnt, max_lvt_cnt)(const unsafe_u2**) resource_reallocate_bytes((char*)(localvariable_table_start ), (lvt_cnt) * sizeof(const unsafe_u2*), (max_lvt_cnt) * sizeof (const unsafe_u2*)); | ||||||||||||
2475 | } | ||||||||||||
2476 | localvariable_table_start[lvt_cnt] = | ||||||||||||
2477 | parse_localvariable_table(cfs, | ||||||||||||
2478 | code_length, | ||||||||||||
2479 | max_locals, | ||||||||||||
2480 | code_attribute_length, | ||||||||||||
2481 | &localvariable_table_length[lvt_cnt], | ||||||||||||
2482 | false, // is not LVTT | ||||||||||||
2483 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2484 | total_lvt_length += localvariable_table_length[lvt_cnt]; | ||||||||||||
2485 | lvt_cnt++; | ||||||||||||
2486 | } else if (LoadLocalVariableTypeTables && | ||||||||||||
2487 | _major_version >= JAVA_1_5_VERSION49 && | ||||||||||||
2488 | cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_type_table()) { | ||||||||||||
2489 | if (!lvt_allocated) { | ||||||||||||
2490 | localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD((u2*) resource_allocate_bytes(__the_thread__, (256) * sizeof( u2)) | ||||||||||||
2491 | THREAD, u2, INITIAL_MAX_LVT_NUMBER)(u2*) resource_allocate_bytes(__the_thread__, (256) * sizeof( u2)); | ||||||||||||
2492 | localvariable_table_start = NEW_RESOURCE_ARRAY_IN_THREAD((const unsafe_u2**) resource_allocate_bytes(__the_thread__, ( 256) * sizeof(const unsafe_u2*)) | ||||||||||||
2493 | THREAD, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER)(const unsafe_u2**) resource_allocate_bytes(__the_thread__, ( 256) * sizeof(const unsafe_u2*)); | ||||||||||||
2494 | localvariable_type_table_length = NEW_RESOURCE_ARRAY_IN_THREAD((u2*) resource_allocate_bytes(__the_thread__, (256) * sizeof( u2)) | ||||||||||||
2495 | THREAD, u2, INITIAL_MAX_LVT_NUMBER)(u2*) resource_allocate_bytes(__the_thread__, (256) * sizeof( u2)); | ||||||||||||
2496 | localvariable_type_table_start = NEW_RESOURCE_ARRAY_IN_THREAD((const unsafe_u2**) resource_allocate_bytes(__the_thread__, ( 256) * sizeof(const unsafe_u2*)) | ||||||||||||
2497 | THREAD, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER)(const unsafe_u2**) resource_allocate_bytes(__the_thread__, ( 256) * sizeof(const unsafe_u2*)); | ||||||||||||
2498 | lvt_allocated = true; | ||||||||||||
2499 | } | ||||||||||||
2500 | // Parse local variable type table | ||||||||||||
2501 | if (lvtt_cnt == max_lvtt_cnt) { | ||||||||||||
2502 | max_lvtt_cnt <<= 1; | ||||||||||||
2503 | localvariable_type_table_length = REALLOC_RESOURCE_ARRAY(u2, localvariable_type_table_length, lvtt_cnt, max_lvtt_cnt)(u2*) resource_reallocate_bytes((char*)(localvariable_type_table_length ), (lvtt_cnt) * sizeof(u2), (max_lvtt_cnt) * sizeof(u2)); | ||||||||||||
2504 | localvariable_type_table_start = REALLOC_RESOURCE_ARRAY(const unsafe_u2*, localvariable_type_table_start, lvtt_cnt, max_lvtt_cnt)(const unsafe_u2**) resource_reallocate_bytes((char*)(localvariable_type_table_start ), (lvtt_cnt) * sizeof(const unsafe_u2*), (max_lvtt_cnt) * sizeof (const unsafe_u2*)); | ||||||||||||
2505 | } | ||||||||||||
2506 | localvariable_type_table_start[lvtt_cnt] = | ||||||||||||
2507 | parse_localvariable_table(cfs, | ||||||||||||
2508 | code_length, | ||||||||||||
2509 | max_locals, | ||||||||||||
2510 | code_attribute_length, | ||||||||||||
2511 | &localvariable_type_table_length[lvtt_cnt], | ||||||||||||
2512 | true, // is LVTT | ||||||||||||
2513 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2514 | lvtt_cnt++; | ||||||||||||
2515 | } else if (_major_version >= Verifier::STACKMAP_ATTRIBUTE_MAJOR_VERSION && | ||||||||||||
2516 | cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_stack_map_table()) { | ||||||||||||
2517 | // Stack map is only needed by the new verifier in JDK1.5. | ||||||||||||
2518 | if (parsed_stackmap_attribute) { | ||||||||||||
2519 | classfile_parse_error("Multiple StackMapTable attributes in class file %s", THREAD__the_thread__); | ||||||||||||
2520 | return NULL__null; | ||||||||||||
2521 | } | ||||||||||||
2522 | stackmap_data = parse_stackmap_table(cfs, code_attribute_length, _need_verify, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2523 | stackmap_data_length = code_attribute_length; | ||||||||||||
2524 | parsed_stackmap_attribute = true; | ||||||||||||
2525 | } else { | ||||||||||||
2526 | // Skip unknown attributes | ||||||||||||
2527 | cfs->skip_u1(code_attribute_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2528 | } | ||||||||||||
2529 | } | ||||||||||||
2530 | // check method attribute length | ||||||||||||
2531 | if (_need_verify) { | ||||||||||||
2532 | guarantee_property(method_attribute_length == calculated_attribute_length, | ||||||||||||
2533 | "Code segment has wrong length in class file %s", | ||||||||||||
2534 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2535 | } | ||||||||||||
2536 | } else if (method_attribute_name == vmSymbols::tag_exceptions()) { | ||||||||||||
2537 | // Parse Exceptions attribute | ||||||||||||
2538 | if (parsed_checked_exceptions_attribute) { | ||||||||||||
2539 | classfile_parse_error("Multiple Exceptions attributes in class file %s", | ||||||||||||
2540 | THREAD__the_thread__); | ||||||||||||
2541 | return NULL__null; | ||||||||||||
2542 | } | ||||||||||||
2543 | parsed_checked_exceptions_attribute = true; | ||||||||||||
2544 | checked_exceptions_start = | ||||||||||||
2545 | parse_checked_exceptions(cfs, | ||||||||||||
2546 | &checked_exceptions_length, | ||||||||||||
2547 | method_attribute_length, | ||||||||||||
2548 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2549 | } else if (method_attribute_name == vmSymbols::tag_method_parameters()) { | ||||||||||||
2550 | // reject multiple method parameters | ||||||||||||
2551 | if (method_parameters_seen) { | ||||||||||||
2552 | classfile_parse_error("Multiple MethodParameters attributes in class file %s", | ||||||||||||
2553 | THREAD__the_thread__); | ||||||||||||
2554 | return NULL__null; | ||||||||||||
2555 | } | ||||||||||||
2556 | method_parameters_seen = true; | ||||||||||||
2557 | method_parameters_length = cfs->get_u1_fast(); | ||||||||||||
2558 | const u2 real_length = (method_parameters_length * 4u) + 1u; | ||||||||||||
2559 | if (method_attribute_length != real_length) { | ||||||||||||
2560 | classfile_parse_error( | ||||||||||||
2561 | "Invalid MethodParameters method attribute length %u in class file", | ||||||||||||
2562 | method_attribute_length, THREAD__the_thread__); | ||||||||||||
2563 | return NULL__null; | ||||||||||||
2564 | } | ||||||||||||
2565 | method_parameters_data = cfs->current(); | ||||||||||||
2566 | cfs->skip_u2_fast(method_parameters_length); | ||||||||||||
2567 | cfs->skip_u2_fast(method_parameters_length); | ||||||||||||
2568 | // ignore this attribute if it cannot be reflected | ||||||||||||
2569 | if (!vmClasses::Parameter_klass_loaded()) | ||||||||||||
2570 | method_parameters_length = -1; | ||||||||||||
2571 | } else if (method_attribute_name == vmSymbols::tag_synthetic()) { | ||||||||||||
2572 | if (method_attribute_length != 0) { | ||||||||||||
2573 | classfile_parse_error( | ||||||||||||
2574 | "Invalid Synthetic method attribute length %u in class file %s", | ||||||||||||
2575 | method_attribute_length, THREAD__the_thread__); | ||||||||||||
2576 | return NULL__null; | ||||||||||||
2577 | } | ||||||||||||
2578 | // Should we check that there hasn't already been a synthetic attribute? | ||||||||||||
2579 | access_flags.set_is_synthetic(); | ||||||||||||
2580 | } else if (method_attribute_name == vmSymbols::tag_deprecated()) { // 4276120 | ||||||||||||
2581 | if (method_attribute_length != 0) { | ||||||||||||
2582 | classfile_parse_error( | ||||||||||||
2583 | "Invalid Deprecated method attribute length %u in class file %s", | ||||||||||||
2584 | method_attribute_length, THREAD__the_thread__); | ||||||||||||
2585 | return NULL__null; | ||||||||||||
2586 | } | ||||||||||||
2587 | } else if (_major_version >= JAVA_1_5_VERSION49) { | ||||||||||||
2588 | if (method_attribute_name == vmSymbols::tag_signature()) { | ||||||||||||
2589 | if (generic_signature_index != 0) { | ||||||||||||
2590 | classfile_parse_error( | ||||||||||||
2591 | "Multiple Signature attributes for method in class file %s", | ||||||||||||
2592 | THREAD__the_thread__); | ||||||||||||
2593 | return NULL__null; | ||||||||||||
2594 | } | ||||||||||||
2595 | if (method_attribute_length != 2) { | ||||||||||||
2596 | classfile_parse_error( | ||||||||||||
2597 | "Invalid Signature attribute length %u in class file %s", | ||||||||||||
2598 | method_attribute_length, THREAD__the_thread__); | ||||||||||||
2599 | return NULL__null; | ||||||||||||
2600 | } | ||||||||||||
2601 | generic_signature_index = parse_generic_signature_attribute(cfs, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2602 | } else if (method_attribute_name == vmSymbols::tag_runtime_visible_annotations()) { | ||||||||||||
2603 | if (runtime_visible_annotations != NULL__null) { | ||||||||||||
2604 | classfile_parse_error( | ||||||||||||
2605 | "Multiple RuntimeVisibleAnnotations attributes for method in class file %s", | ||||||||||||
2606 | THREAD__the_thread__); | ||||||||||||
2607 | return NULL__null; | ||||||||||||
2608 | } | ||||||||||||
2609 | runtime_visible_annotations_length = method_attribute_length; | ||||||||||||
2610 | runtime_visible_annotations = cfs->current(); | ||||||||||||
2611 | assert(runtime_visible_annotations != NULL, "null visible annotations")do { if (!(runtime_visible_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2611, "assert(" "runtime_visible_annotations != __null" ") failed" , "null visible annotations"); ::breakpoint(); } } while (0); | ||||||||||||
2612 | cfs->guarantee_more(runtime_visible_annotations_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2613 | parse_annotations(cp, | ||||||||||||
2614 | runtime_visible_annotations, | ||||||||||||
2615 | runtime_visible_annotations_length, | ||||||||||||
2616 | &parsed_annotations, | ||||||||||||
2617 | _loader_data, | ||||||||||||
2618 | _can_access_vm_annotations); | ||||||||||||
2619 | cfs->skip_u1_fast(runtime_visible_annotations_length); | ||||||||||||
2620 | } else if (method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { | ||||||||||||
2621 | if (runtime_invisible_annotations_exists) { | ||||||||||||
2622 | classfile_parse_error( | ||||||||||||
2623 | "Multiple RuntimeInvisibleAnnotations attributes for method in class file %s", | ||||||||||||
2624 | THREAD__the_thread__); | ||||||||||||
2625 | return NULL__null; | ||||||||||||
2626 | } | ||||||||||||
2627 | runtime_invisible_annotations_exists = true; | ||||||||||||
2628 | if (PreserveAllAnnotations) { | ||||||||||||
2629 | runtime_invisible_annotations_length = method_attribute_length; | ||||||||||||
2630 | runtime_invisible_annotations = cfs->current(); | ||||||||||||
2631 | assert(runtime_invisible_annotations != NULL, "null invisible annotations")do { if (!(runtime_invisible_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2631, "assert(" "runtime_invisible_annotations != __null" ") failed" , "null invisible annotations"); ::breakpoint(); } } while (0 ); | ||||||||||||
2632 | } | ||||||||||||
2633 | cfs->skip_u1(method_attribute_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2634 | } else if (method_attribute_name == vmSymbols::tag_runtime_visible_parameter_annotations()) { | ||||||||||||
2635 | if (runtime_visible_parameter_annotations != NULL__null) { | ||||||||||||
2636 | classfile_parse_error( | ||||||||||||
2637 | "Multiple RuntimeVisibleParameterAnnotations attributes for method in class file %s", | ||||||||||||
2638 | THREAD__the_thread__); | ||||||||||||
2639 | return NULL__null; | ||||||||||||
2640 | } | ||||||||||||
2641 | runtime_visible_parameter_annotations_length = method_attribute_length; | ||||||||||||
2642 | runtime_visible_parameter_annotations = cfs->current(); | ||||||||||||
2643 | assert(runtime_visible_parameter_annotations != NULL, "null visible parameter annotations")do { if (!(runtime_visible_parameter_annotations != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2643, "assert(" "runtime_visible_parameter_annotations != __null" ") failed", "null visible parameter annotations"); ::breakpoint (); } } while (0); | ||||||||||||
2644 | cfs->skip_u1(runtime_visible_parameter_annotations_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2645 | } else if (method_attribute_name == vmSymbols::tag_runtime_invisible_parameter_annotations()) { | ||||||||||||
2646 | if (runtime_invisible_parameter_annotations_exists) { | ||||||||||||
2647 | classfile_parse_error( | ||||||||||||
2648 | "Multiple RuntimeInvisibleParameterAnnotations attributes for method in class file %s", | ||||||||||||
2649 | THREAD__the_thread__); | ||||||||||||
2650 | return NULL__null; | ||||||||||||
2651 | } | ||||||||||||
2652 | runtime_invisible_parameter_annotations_exists = true; | ||||||||||||
2653 | if (PreserveAllAnnotations) { | ||||||||||||
2654 | runtime_invisible_parameter_annotations_length = method_attribute_length; | ||||||||||||
2655 | runtime_invisible_parameter_annotations = cfs->current(); | ||||||||||||
2656 | assert(runtime_invisible_parameter_annotations != NULL,do { if (!(runtime_invisible_parameter_annotations != __null) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2657, "assert(" "runtime_invisible_parameter_annotations != __null" ") failed", "null invisible parameter annotations"); ::breakpoint (); } } while (0) | ||||||||||||
2657 | "null invisible parameter annotations")do { if (!(runtime_invisible_parameter_annotations != __null) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2657, "assert(" "runtime_invisible_parameter_annotations != __null" ") failed", "null invisible parameter annotations"); ::breakpoint (); } } while (0); | ||||||||||||
2658 | } | ||||||||||||
2659 | cfs->skip_u1(method_attribute_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2660 | } else if (method_attribute_name == vmSymbols::tag_annotation_default()) { | ||||||||||||
2661 | if (annotation_default != NULL__null) { | ||||||||||||
2662 | classfile_parse_error( | ||||||||||||
2663 | "Multiple AnnotationDefault attributes for method in class file %s", | ||||||||||||
2664 | THREAD__the_thread__); | ||||||||||||
2665 | return NULL__null; | ||||||||||||
2666 | } | ||||||||||||
2667 | annotation_default_length = method_attribute_length; | ||||||||||||
2668 | annotation_default = cfs->current(); | ||||||||||||
2669 | assert(annotation_default != NULL, "null annotation default")do { if (!(annotation_default != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2669, "assert(" "annotation_default != __null" ") failed", "null annotation default" ); ::breakpoint(); } } while (0); | ||||||||||||
2670 | cfs->skip_u1(annotation_default_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2671 | } else if (method_attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) { | ||||||||||||
2672 | if (runtime_visible_type_annotations != NULL__null) { | ||||||||||||
2673 | classfile_parse_error( | ||||||||||||
2674 | "Multiple RuntimeVisibleTypeAnnotations attributes for method in class file %s", | ||||||||||||
2675 | THREAD__the_thread__); | ||||||||||||
2676 | return NULL__null; | ||||||||||||
2677 | } | ||||||||||||
2678 | runtime_visible_type_annotations_length = method_attribute_length; | ||||||||||||
2679 | runtime_visible_type_annotations = cfs->current(); | ||||||||||||
2680 | assert(runtime_visible_type_annotations != NULL, "null visible type annotations")do { if (!(runtime_visible_type_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2680, "assert(" "runtime_visible_type_annotations != __null" ") failed", "null visible type annotations"); ::breakpoint() ; } } while (0); | ||||||||||||
2681 | // No need for the VM to parse Type annotations | ||||||||||||
2682 | cfs->skip_u1(runtime_visible_type_annotations_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2683 | } else if (method_attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) { | ||||||||||||
2684 | if (runtime_invisible_type_annotations_exists) { | ||||||||||||
2685 | classfile_parse_error( | ||||||||||||
2686 | "Multiple RuntimeInvisibleTypeAnnotations attributes for method in class file %s", | ||||||||||||
2687 | THREAD__the_thread__); | ||||||||||||
2688 | return NULL__null; | ||||||||||||
2689 | } else { | ||||||||||||
2690 | runtime_invisible_type_annotations_exists = true; | ||||||||||||
2691 | } | ||||||||||||
2692 | if (PreserveAllAnnotations) { | ||||||||||||
2693 | runtime_invisible_type_annotations_length = method_attribute_length; | ||||||||||||
2694 | runtime_invisible_type_annotations = cfs->current(); | ||||||||||||
2695 | assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations")do { if (!(runtime_invisible_type_annotations != __null)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2695, "assert(" "runtime_invisible_type_annotations != __null" ") failed", "null invisible type annotations"); ::breakpoint (); } } while (0); | ||||||||||||
2696 | } | ||||||||||||
2697 | cfs->skip_u1(method_attribute_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2698 | } else { | ||||||||||||
2699 | // Skip unknown attributes | ||||||||||||
2700 | cfs->skip_u1(method_attribute_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2701 | } | ||||||||||||
2702 | } else { | ||||||||||||
2703 | // Skip unknown attributes | ||||||||||||
2704 | cfs->skip_u1(method_attribute_length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2705 | } | ||||||||||||
2706 | } | ||||||||||||
2707 | |||||||||||||
2708 | if (linenumber_table
| ||||||||||||
2709 | linenumber_table->write_terminator(); | ||||||||||||
2710 | linenumber_table_length = linenumber_table->position(); | ||||||||||||
2711 | } | ||||||||||||
2712 | |||||||||||||
2713 | // Make sure there's at least one Code attribute in non-native/non-abstract method | ||||||||||||
2714 | if (_need_verify
| ||||||||||||
2715 | guarantee_property(access_flags.is_native() || | ||||||||||||
2716 | access_flags.is_abstract() || | ||||||||||||
2717 | parsed_code_attribute, | ||||||||||||
2718 | "Absent Code attribute in method that is not native or abstract in class file %s", | ||||||||||||
2719 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2720 | } | ||||||||||||
2721 | |||||||||||||
2722 | // All sizing information for a Method* is finally available, now create it | ||||||||||||
2723 | InlineTableSizes sizes( | ||||||||||||
2724 | total_lvt_length, | ||||||||||||
2725 | linenumber_table_length, | ||||||||||||
2726 | exception_table_length, | ||||||||||||
2727 | checked_exceptions_length, | ||||||||||||
2728 | method_parameters_length, | ||||||||||||
2729 | generic_signature_index, | ||||||||||||
2730 | runtime_visible_annotations_length + | ||||||||||||
2731 | runtime_invisible_annotations_length, | ||||||||||||
2732 | runtime_visible_parameter_annotations_length + | ||||||||||||
2733 | runtime_invisible_parameter_annotations_length, | ||||||||||||
2734 | runtime_visible_type_annotations_length + | ||||||||||||
2735 | runtime_invisible_type_annotations_length, | ||||||||||||
2736 | annotation_default_length, | ||||||||||||
2737 | 0); | ||||||||||||
2738 | |||||||||||||
2739 | Method* const m = Method::allocate(_loader_data, | ||||||||||||
2740 | code_length, | ||||||||||||
2741 | access_flags, | ||||||||||||
2742 | &sizes, | ||||||||||||
2743 | ConstMethod::NORMAL, | ||||||||||||
2744 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2745 | |||||||||||||
2746 | ClassLoadingService::add_class_method_size(m->size()*wordSize); | ||||||||||||
2747 | |||||||||||||
2748 | // Fill in information from fixed part (access_flags already set) | ||||||||||||
2749 | m->set_constants(_cp); | ||||||||||||
2750 | m->set_name_index(name_index); | ||||||||||||
2751 | m->set_signature_index(signature_index); | ||||||||||||
2752 | m->compute_from_signature(cp->symbol_at(signature_index)); | ||||||||||||
2753 | assert(args_size < 0 || args_size == m->size_of_parameters(), "")do { if (!(args_size < 0 || args_size == m->size_of_parameters ())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2753, "assert(" "args_size < 0 || args_size == m->size_of_parameters()" ") failed", ""); ::breakpoint(); } } while (0); | ||||||||||||
2754 | |||||||||||||
2755 | // Fill in code attribute information | ||||||||||||
2756 | m->set_max_stack(max_stack); | ||||||||||||
2757 | m->set_max_locals(max_locals); | ||||||||||||
2758 | if (stackmap_data
| ||||||||||||
2759 | m->constMethod()->copy_stackmap_data(_loader_data, | ||||||||||||
2760 | (u1*)stackmap_data, | ||||||||||||
2761 | stackmap_data_length, | ||||||||||||
2762 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2763 | } | ||||||||||||
2764 | |||||||||||||
2765 | // Copy byte codes | ||||||||||||
2766 | m->set_code((u1*)code_start); | ||||||||||||
2767 | |||||||||||||
2768 | // Copy line number table | ||||||||||||
2769 | if (linenumber_table != NULL__null) { | ||||||||||||
2770 | memcpy(m->compressed_linenumber_table(), | ||||||||||||
2771 | linenumber_table->buffer(), | ||||||||||||
2772 | linenumber_table_length); | ||||||||||||
2773 | } | ||||||||||||
2774 | |||||||||||||
2775 | // Copy exception table | ||||||||||||
2776 | if (exception_table_length > 0) { | ||||||||||||
2777 | Copy::conjoint_swap_if_needed<Endian::JAVA>(exception_table_start, | ||||||||||||
2778 | m->exception_table_start(), | ||||||||||||
2779 | exception_table_length * sizeof(ExceptionTableElement), | ||||||||||||
2780 | sizeof(u2)); | ||||||||||||
2781 | } | ||||||||||||
2782 | |||||||||||||
2783 | // Copy method parameters | ||||||||||||
2784 | if (method_parameters_length > 0) { | ||||||||||||
2785 | MethodParametersElement* elem = m->constMethod()->method_parameters_start(); | ||||||||||||
2786 | for (int i = 0; i < method_parameters_length; i++) { | ||||||||||||
2787 | elem[i].name_cp_index = Bytes::get_Java_u2((address)method_parameters_data); | ||||||||||||
2788 | method_parameters_data += 2; | ||||||||||||
2789 | elem[i].flags = Bytes::get_Java_u2((address)method_parameters_data); | ||||||||||||
2790 | method_parameters_data += 2; | ||||||||||||
2791 | } | ||||||||||||
2792 | } | ||||||||||||
2793 | |||||||||||||
2794 | // Copy checked exceptions | ||||||||||||
2795 | if (checked_exceptions_length > 0) { | ||||||||||||
2796 | Copy::conjoint_swap_if_needed<Endian::JAVA>(checked_exceptions_start, | ||||||||||||
2797 | m->checked_exceptions_start(), | ||||||||||||
2798 | checked_exceptions_length * sizeof(CheckedExceptionElement), | ||||||||||||
2799 | sizeof(u2)); | ||||||||||||
2800 | } | ||||||||||||
2801 | |||||||||||||
2802 | // Copy class file LVT's/LVTT's into the HotSpot internal LVT. | ||||||||||||
2803 | if (total_lvt_length > 0) { | ||||||||||||
2804 | promoted_flags->set_has_localvariable_table(); | ||||||||||||
2805 | copy_localvariable_table(m->constMethod(), | ||||||||||||
2806 | lvt_cnt, | ||||||||||||
2807 | localvariable_table_length, | ||||||||||||
2808 | localvariable_table_start, | ||||||||||||
2809 | lvtt_cnt, | ||||||||||||
2810 | localvariable_type_table_length, | ||||||||||||
2811 | localvariable_type_table_start, | ||||||||||||
2812 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2813 | } | ||||||||||||
2814 | |||||||||||||
2815 | if (parsed_annotations.has_any_annotations()) | ||||||||||||
2816 | parsed_annotations.apply_to(methodHandle(THREAD__the_thread__, m)); | ||||||||||||
2817 | |||||||||||||
2818 | if (is_hidden()) { // Mark methods in hidden classes as 'hidden'. | ||||||||||||
2819 | m->set_hidden(true); | ||||||||||||
2820 | } | ||||||||||||
2821 | |||||||||||||
2822 | // Copy annotations | ||||||||||||
2823 | copy_method_annotations(m->constMethod(), | ||||||||||||
2824 | runtime_visible_annotations, | ||||||||||||
2825 | runtime_visible_annotations_length, | ||||||||||||
2826 | runtime_invisible_annotations, | ||||||||||||
2827 | runtime_invisible_annotations_length, | ||||||||||||
2828 | runtime_visible_parameter_annotations, | ||||||||||||
2829 | runtime_visible_parameter_annotations_length, | ||||||||||||
2830 | runtime_invisible_parameter_annotations, | ||||||||||||
2831 | runtime_invisible_parameter_annotations_length, | ||||||||||||
2832 | runtime_visible_type_annotations, | ||||||||||||
2833 | runtime_visible_type_annotations_length, | ||||||||||||
2834 | runtime_invisible_type_annotations, | ||||||||||||
2835 | runtime_invisible_type_annotations_length, | ||||||||||||
2836 | annotation_default, | ||||||||||||
2837 | annotation_default_length, | ||||||||||||
2838 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
2839 | |||||||||||||
2840 | if (InstanceKlass::is_finalization_enabled() && | ||||||||||||
2841 | name == vmSymbols::finalize_method_name() && | ||||||||||||
2842 | signature == vmSymbols::void_method_signature()) { | ||||||||||||
2843 | if (m->is_empty_method()) { | ||||||||||||
2844 | _has_empty_finalizer = true; | ||||||||||||
2845 | } else { | ||||||||||||
2846 | _has_finalizer = true; | ||||||||||||
2847 | } | ||||||||||||
2848 | } | ||||||||||||
2849 | if (name == vmSymbols::object_initializer_name() && | ||||||||||||
2850 | signature == vmSymbols::void_method_signature() && | ||||||||||||
2851 | m->is_vanilla_constructor()) { | ||||||||||||
2852 | _has_vanilla_constructor = true; | ||||||||||||
2853 | } | ||||||||||||
2854 | |||||||||||||
2855 | NOT_PRODUCT(m->verify())m->verify(); | ||||||||||||
2856 | return m; | ||||||||||||
2857 | } | ||||||||||||
2858 | |||||||||||||
2859 | |||||||||||||
2860 | // The promoted_flags parameter is used to pass relevant access_flags | ||||||||||||
2861 | // from the methods back up to the containing klass. These flag values | ||||||||||||
2862 | // are added to klass's access_flags. | ||||||||||||
2863 | // Side-effects: populates the _methods field in the parser | ||||||||||||
2864 | void ClassFileParser::parse_methods(const ClassFileStream* const cfs, | ||||||||||||
2865 | bool is_interface, | ||||||||||||
2866 | AccessFlags* promoted_flags, | ||||||||||||
2867 | bool* has_final_method, | ||||||||||||
2868 | bool* declares_nonstatic_concrete_methods, | ||||||||||||
2869 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
2870 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2870, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
2871 | assert(promoted_flags != NULL, "invariant")do { if (!(promoted_flags != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2871, "assert(" "promoted_flags != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
2872 | assert(has_final_method != NULL, "invariant")do { if (!(has_final_method != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2872, "assert(" "has_final_method != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
2873 | assert(declares_nonstatic_concrete_methods != NULL, "invariant")do { if (!(declares_nonstatic_concrete_methods != __null)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2873, "assert(" "declares_nonstatic_concrete_methods != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
2874 | |||||||||||||
2875 | assert(NULL == _methods, "invariant")do { if (!(__null == _methods)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2875, "assert(" "__null == _methods" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
2876 | |||||||||||||
2877 | cfs->guarantee_more(2, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // length | ||||||||||||
2878 | const u2 length = cfs->get_u2_fast(); | ||||||||||||
2879 | if (length == 0) { | ||||||||||||
2880 | _methods = Universe::the_empty_method_array(); | ||||||||||||
2881 | } else { | ||||||||||||
2882 | _methods = MetadataFactory::new_array<Method*>(_loader_data, | ||||||||||||
2883 | length, | ||||||||||||
2884 | NULL__null, | ||||||||||||
2885 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
2886 | |||||||||||||
2887 | for (int index = 0; index < length; index++) { | ||||||||||||
2888 | Method* method = parse_method(cfs, | ||||||||||||
2889 | is_interface, | ||||||||||||
2890 | _cp, | ||||||||||||
2891 | promoted_flags, | ||||||||||||
2892 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
2893 | |||||||||||||
2894 | if (method->is_final()) { | ||||||||||||
2895 | *has_final_method = true; | ||||||||||||
2896 | } | ||||||||||||
2897 | // declares_nonstatic_concrete_methods: declares concrete instance methods, any access flags | ||||||||||||
2898 | // used for interface initialization, and default method inheritance analysis | ||||||||||||
2899 | if (is_interface && !(*declares_nonstatic_concrete_methods) | ||||||||||||
2900 | && !method->is_abstract() && !method->is_static()) { | ||||||||||||
2901 | *declares_nonstatic_concrete_methods = true; | ||||||||||||
2902 | } | ||||||||||||
2903 | _methods->at_put(index, method); | ||||||||||||
2904 | } | ||||||||||||
2905 | |||||||||||||
2906 | if (_need_verify && length > 1) { | ||||||||||||
2907 | // Check duplicated methods | ||||||||||||
2908 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
2909 | NameSigHash** names_and_sigs = NEW_RESOURCE_ARRAY_IN_THREAD((NameSigHash**) resource_allocate_bytes(__the_thread__, (HASH_ROW_SIZE ) * sizeof(NameSigHash*)) | ||||||||||||
2910 | THREAD, NameSigHash*, HASH_ROW_SIZE)(NameSigHash**) resource_allocate_bytes(__the_thread__, (HASH_ROW_SIZE ) * sizeof(NameSigHash*)); | ||||||||||||
2911 | initialize_hashtable(names_and_sigs); | ||||||||||||
2912 | bool dup = false; | ||||||||||||
2913 | const Symbol* name = NULL__null; | ||||||||||||
2914 | const Symbol* sig = NULL__null; | ||||||||||||
2915 | { | ||||||||||||
2916 | debug_only(NoSafepointVerifier nsv;)NoSafepointVerifier nsv; | ||||||||||||
2917 | for (int i = 0; i < length; i++) { | ||||||||||||
2918 | const Method* const m = _methods->at(i); | ||||||||||||
2919 | name = m->name(); | ||||||||||||
2920 | sig = m->signature(); | ||||||||||||
2921 | // If no duplicates, add name/signature in hashtable names_and_sigs. | ||||||||||||
2922 | if (!put_after_lookup(name, sig, names_and_sigs)) { | ||||||||||||
2923 | dup = true; | ||||||||||||
2924 | break; | ||||||||||||
2925 | } | ||||||||||||
2926 | } | ||||||||||||
2927 | } | ||||||||||||
2928 | if (dup) { | ||||||||||||
2929 | classfile_parse_error("Duplicate method name \"%s\" with signature \"%s\" in class file %s", | ||||||||||||
2930 | name->as_C_string(), sig->as_klass_external_name(), THREAD__the_thread__); | ||||||||||||
2931 | } | ||||||||||||
2932 | } | ||||||||||||
2933 | } | ||||||||||||
2934 | } | ||||||||||||
2935 | |||||||||||||
2936 | static const intArray* sort_methods(Array<Method*>* methods) { | ||||||||||||
2937 | const int length = methods->length(); | ||||||||||||
2938 | // If JVMTI original method ordering or sharing is enabled we have to | ||||||||||||
2939 | // remember the original class file ordering. | ||||||||||||
2940 | // We temporarily use the vtable_index field in the Method* to store the | ||||||||||||
2941 | // class file index, so we can read in after calling qsort. | ||||||||||||
2942 | // Put the method ordering in the shared archive. | ||||||||||||
2943 | if (JvmtiExport::can_maintain_original_method_order() || Arguments::is_dumping_archive()) { | ||||||||||||
2944 | for (int index = 0; index < length; index++) { | ||||||||||||
2945 | Method* const m = methods->at(index); | ||||||||||||
2946 | assert(!m->valid_vtable_index(), "vtable index should not be set")do { if (!(!m->valid_vtable_index())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2946, "assert(" "!m->valid_vtable_index()" ") failed", "vtable index should not be set" ); ::breakpoint(); } } while (0); | ||||||||||||
2947 | m->set_vtable_index(index); | ||||||||||||
2948 | } | ||||||||||||
2949 | } | ||||||||||||
2950 | // Sort method array by ascending method name (for faster lookups & vtable construction) | ||||||||||||
2951 | // Note that the ordering is not alphabetical, see Symbol::fast_compare | ||||||||||||
2952 | Method::sort_methods(methods); | ||||||||||||
2953 | |||||||||||||
2954 | intArray* method_ordering = NULL__null; | ||||||||||||
2955 | // If JVMTI original method ordering or sharing is enabled construct int | ||||||||||||
2956 | // array remembering the original ordering | ||||||||||||
2957 | if (JvmtiExport::can_maintain_original_method_order() || Arguments::is_dumping_archive()) { | ||||||||||||
2958 | method_ordering = new intArray(length, length, -1); | ||||||||||||
2959 | for (int index = 0; index < length; index++) { | ||||||||||||
2960 | Method* const m = methods->at(index); | ||||||||||||
2961 | const int old_index = m->vtable_index(); | ||||||||||||
2962 | assert(old_index >= 0 && old_index < length, "invalid method index")do { if (!(old_index >= 0 && old_index < length )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2962, "assert(" "old_index >= 0 && old_index < length" ") failed", "invalid method index"); ::breakpoint(); } } while (0); | ||||||||||||
2963 | method_ordering->at_put(index, old_index); | ||||||||||||
2964 | m->set_vtable_index(Method::invalid_vtable_index); | ||||||||||||
2965 | } | ||||||||||||
2966 | } | ||||||||||||
2967 | return method_ordering; | ||||||||||||
2968 | } | ||||||||||||
2969 | |||||||||||||
2970 | // Parse generic_signature attribute for methods and fields | ||||||||||||
2971 | u2 ClassFileParser::parse_generic_signature_attribute(const ClassFileStream* const cfs, | ||||||||||||
2972 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
2973 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2973, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
2974 | |||||||||||||
2975 | cfs->guarantee_more(2, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); // generic_signature_index | ||||||||||||
2976 | const u2 generic_signature_index = cfs->get_u2_fast(); | ||||||||||||
2977 | check_property( | ||||||||||||
2978 | valid_symbol_at(generic_signature_index), | ||||||||||||
2979 | "Invalid Signature attribute at constant pool index %u in class file %s", | ||||||||||||
2980 | generic_signature_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
2981 | return generic_signature_index; | ||||||||||||
2982 | } | ||||||||||||
2983 | |||||||||||||
2984 | void ClassFileParser::parse_classfile_sourcefile_attribute(const ClassFileStream* const cfs, | ||||||||||||
2985 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
2986 | |||||||||||||
2987 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 2987, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
2988 | |||||||||||||
2989 | cfs->guarantee_more(2, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // sourcefile_index | ||||||||||||
2990 | const u2 sourcefile_index = cfs->get_u2_fast(); | ||||||||||||
2991 | check_property( | ||||||||||||
2992 | valid_symbol_at(sourcefile_index), | ||||||||||||
2993 | "Invalid SourceFile attribute at constant pool index %u in class file %s", | ||||||||||||
2994 | sourcefile_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
2995 | set_class_sourcefile_index(sourcefile_index); | ||||||||||||
2996 | } | ||||||||||||
2997 | |||||||||||||
2998 | void ClassFileParser::parse_classfile_source_debug_extension_attribute(const ClassFileStream* const cfs, | ||||||||||||
2999 | int length, | ||||||||||||
3000 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
3001 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3001, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
3002 | |||||||||||||
3003 | const u1* const sde_buffer = cfs->current(); | ||||||||||||
3004 | assert(sde_buffer != NULL, "null sde buffer")do { if (!(sde_buffer != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3004, "assert(" "sde_buffer != __null" ") failed", "null sde buffer" ); ::breakpoint(); } } while (0); | ||||||||||||
3005 | |||||||||||||
3006 | // Don't bother storing it if there is no way to retrieve it | ||||||||||||
3007 | if (JvmtiExport::can_get_source_debug_extension()) { | ||||||||||||
3008 | assert((length+1) > length, "Overflow checking")do { if (!((length+1) > length)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3008, "assert(" "(length+1) > length" ") failed", "Overflow checking" ); ::breakpoint(); } } while (0); | ||||||||||||
3009 | u1* const sde = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, u1, length+1)(u1*) resource_allocate_bytes(__the_thread__, (length+1) * sizeof (u1)); | ||||||||||||
3010 | for (int i = 0; i < length; i++) { | ||||||||||||
3011 | sde[i] = sde_buffer[i]; | ||||||||||||
3012 | } | ||||||||||||
3013 | sde[length] = '\0'; | ||||||||||||
3014 | set_class_sde_buffer((const char*)sde, length); | ||||||||||||
3015 | } | ||||||||||||
3016 | // Got utf8 string, set stream position forward | ||||||||||||
3017 | cfs->skip_u1(length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3018 | } | ||||||||||||
3019 | |||||||||||||
3020 | |||||||||||||
3021 | // Inner classes can be static, private or protected (classic VM does this) | ||||||||||||
3022 | #define RECOGNIZED_INNER_CLASS_MODIFIERS( (JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SUPER | JVM_ACC_INTERFACE | JVM_ACC_ABSTRACT | JVM_ACC_ANNOTATION | JVM_ACC_ENUM | JVM_ACC_SYNTHETIC ) | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC ) ( JVM_RECOGNIZED_CLASS_MODIFIERS(JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SUPER | JVM_ACC_INTERFACE | JVM_ACC_ABSTRACT | JVM_ACC_ANNOTATION | JVM_ACC_ENUM | JVM_ACC_SYNTHETIC ) | \ | ||||||||||||
3023 | JVM_ACC_PRIVATE | \ | ||||||||||||
3024 | JVM_ACC_PROTECTED | \ | ||||||||||||
3025 | JVM_ACC_STATIC \ | ||||||||||||
3026 | ) | ||||||||||||
3027 | |||||||||||||
3028 | // Find index of the InnerClasses entry for the specified inner_class_info_index. | ||||||||||||
3029 | // Return -1 if none is found. | ||||||||||||
3030 | static int inner_classes_find_index(const Array<u2>* inner_classes, int inner, const ConstantPool* cp, int length) { | ||||||||||||
3031 | Symbol* cp_klass_name = cp->klass_name_at(inner); | ||||||||||||
3032 | for (int idx = 0; idx < length; idx += InstanceKlass::inner_class_next_offset) { | ||||||||||||
3033 | int idx_inner = inner_classes->at(idx + InstanceKlass::inner_class_inner_class_info_offset); | ||||||||||||
3034 | if (cp->klass_name_at(idx_inner) == cp_klass_name) { | ||||||||||||
3035 | return idx; | ||||||||||||
3036 | } | ||||||||||||
3037 | } | ||||||||||||
3038 | return -1; | ||||||||||||
3039 | } | ||||||||||||
3040 | |||||||||||||
3041 | // Return the outer_class_info_index for the InnerClasses entry containing the | ||||||||||||
3042 | // specified inner_class_info_index. Return -1 if no InnerClasses entry is found. | ||||||||||||
3043 | static int inner_classes_jump_to_outer(const Array<u2>* inner_classes, int inner, const ConstantPool* cp, int length) { | ||||||||||||
3044 | if (inner == 0) return -1; | ||||||||||||
3045 | int idx = inner_classes_find_index(inner_classes, inner, cp, length); | ||||||||||||
3046 | if (idx == -1) return -1; | ||||||||||||
3047 | int result = inner_classes->at(idx + InstanceKlass::inner_class_outer_class_info_offset); | ||||||||||||
3048 | return result; | ||||||||||||
3049 | } | ||||||||||||
3050 | |||||||||||||
3051 | // Return true if circularity is found, false if no circularity is found. | ||||||||||||
3052 | // Use Floyd's cycle finding algorithm. | ||||||||||||
3053 | static bool inner_classes_check_loop_through_outer(const Array<u2>* inner_classes, int idx, const ConstantPool* cp, int length) { | ||||||||||||
3054 | int slow = inner_classes->at(idx + InstanceKlass::inner_class_inner_class_info_offset); | ||||||||||||
3055 | int fast = inner_classes->at(idx + InstanceKlass::inner_class_outer_class_info_offset); | ||||||||||||
3056 | while (fast != -1 && fast != 0) { | ||||||||||||
3057 | if (slow != 0 && (cp->klass_name_at(slow) == cp->klass_name_at(fast))) { | ||||||||||||
3058 | return true; // found a circularity | ||||||||||||
3059 | } | ||||||||||||
3060 | fast = inner_classes_jump_to_outer(inner_classes, fast, cp, length); | ||||||||||||
3061 | if (fast == -1) return false; | ||||||||||||
3062 | fast = inner_classes_jump_to_outer(inner_classes, fast, cp, length); | ||||||||||||
3063 | if (fast == -1) return false; | ||||||||||||
3064 | slow = inner_classes_jump_to_outer(inner_classes, slow, cp, length); | ||||||||||||
3065 | assert(slow != -1, "sanity check")do { if (!(slow != -1)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3065, "assert(" "slow != -1" ") failed", "sanity check"); :: breakpoint(); } } while (0); | ||||||||||||
3066 | } | ||||||||||||
3067 | return false; | ||||||||||||
3068 | } | ||||||||||||
3069 | |||||||||||||
3070 | // Loop through each InnerClasses entry checking for circularities and duplications | ||||||||||||
3071 | // with other entries. If duplicate entries are found then throw CFE. Otherwise, | ||||||||||||
3072 | // return true if a circularity or entries with duplicate inner_class_info_indexes | ||||||||||||
3073 | // are found. | ||||||||||||
3074 | bool ClassFileParser::check_inner_classes_circularity(const ConstantPool* cp, int length, TRAPSJavaThread* __the_thread__) { | ||||||||||||
3075 | // Loop through each InnerClasses entry. | ||||||||||||
3076 | for (int idx = 0; idx < length; idx += InstanceKlass::inner_class_next_offset) { | ||||||||||||
3077 | // Return true if there are circular entries. | ||||||||||||
3078 | if (inner_classes_check_loop_through_outer(_inner_classes, idx, cp, length)) { | ||||||||||||
3079 | return true; | ||||||||||||
3080 | } | ||||||||||||
3081 | // Check if there are duplicate entries or entries with the same inner_class_info_index. | ||||||||||||
3082 | for (int y = idx + InstanceKlass::inner_class_next_offset; y < length; | ||||||||||||
3083 | y += InstanceKlass::inner_class_next_offset) { | ||||||||||||
3084 | |||||||||||||
3085 | // To maintain compatibility, throw an exception if duplicate inner classes | ||||||||||||
3086 | // entries are found. | ||||||||||||
3087 | guarantee_property((_inner_classes->at(idx) != _inner_classes->at(y) || | ||||||||||||
3088 | _inner_classes->at(idx+1) != _inner_classes->at(y+1) || | ||||||||||||
3089 | _inner_classes->at(idx+2) != _inner_classes->at(y+2) || | ||||||||||||
3090 | _inner_classes->at(idx+3) != _inner_classes->at(y+3)), | ||||||||||||
3091 | "Duplicate entry in InnerClasses attribute in class file %s", | ||||||||||||
3092 | CHECK_(true)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return true; (void)(0); | ||||||||||||
3093 | // Return true if there are two entries with the same inner_class_info_index. | ||||||||||||
3094 | if (_inner_classes->at(y) == _inner_classes->at(idx)) { | ||||||||||||
3095 | return true; | ||||||||||||
3096 | } | ||||||||||||
3097 | } | ||||||||||||
3098 | } | ||||||||||||
3099 | return false; | ||||||||||||
3100 | } | ||||||||||||
3101 | |||||||||||||
3102 | // Return number of classes in the inner classes attribute table | ||||||||||||
3103 | u2 ClassFileParser::parse_classfile_inner_classes_attribute(const ClassFileStream* const cfs, | ||||||||||||
3104 | const ConstantPool* cp, | ||||||||||||
3105 | const u1* const inner_classes_attribute_start, | ||||||||||||
3106 | bool parsed_enclosingmethod_attribute, | ||||||||||||
3107 | u2 enclosing_method_class_index, | ||||||||||||
3108 | u2 enclosing_method_method_index, | ||||||||||||
3109 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
3110 | const u1* const current_mark = cfs->current(); | ||||||||||||
3111 | u2 length = 0; | ||||||||||||
3112 | if (inner_classes_attribute_start != NULL__null) { | ||||||||||||
3113 | cfs->set_current(inner_classes_attribute_start); | ||||||||||||
3114 | cfs->guarantee_more(2, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); // length | ||||||||||||
3115 | length = cfs->get_u2_fast(); | ||||||||||||
3116 | } | ||||||||||||
3117 | |||||||||||||
3118 | // 4-tuples of shorts of inner classes data and 2 shorts of enclosing | ||||||||||||
3119 | // method data: | ||||||||||||
3120 | // [inner_class_info_index, | ||||||||||||
3121 | // outer_class_info_index, | ||||||||||||
3122 | // inner_name_index, | ||||||||||||
3123 | // inner_class_access_flags, | ||||||||||||
3124 | // ... | ||||||||||||
3125 | // enclosing_method_class_index, | ||||||||||||
3126 | // enclosing_method_method_index] | ||||||||||||
3127 | const int size = length * 4 + (parsed_enclosingmethod_attribute ? 2 : 0); | ||||||||||||
3128 | Array<u2>* inner_classes = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3129 | _inner_classes = inner_classes; | ||||||||||||
3130 | |||||||||||||
3131 | int index = 0; | ||||||||||||
3132 | cfs->guarantee_more(8 * length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); // 4-tuples of u2 | ||||||||||||
3133 | for (int n = 0; n < length; n++) { | ||||||||||||
3134 | // Inner class index | ||||||||||||
3135 | const u2 inner_class_info_index = cfs->get_u2_fast(); | ||||||||||||
3136 | check_property( | ||||||||||||
3137 | valid_klass_reference_at(inner_class_info_index), | ||||||||||||
3138 | "inner_class_info_index %u has bad constant type in class file %s", | ||||||||||||
3139 | inner_class_info_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3140 | // Outer class index | ||||||||||||
3141 | const u2 outer_class_info_index = cfs->get_u2_fast(); | ||||||||||||
3142 | check_property( | ||||||||||||
3143 | outer_class_info_index == 0 || | ||||||||||||
3144 | valid_klass_reference_at(outer_class_info_index), | ||||||||||||
3145 | "outer_class_info_index %u has bad constant type in class file %s", | ||||||||||||
3146 | outer_class_info_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3147 | |||||||||||||
3148 | if (outer_class_info_index != 0) { | ||||||||||||
3149 | const Symbol* const outer_class_name = cp->klass_name_at(outer_class_info_index); | ||||||||||||
3150 | char* bytes = (char*)outer_class_name->bytes(); | ||||||||||||
3151 | guarantee_property(bytes[0] != JVM_SIGNATURE_ARRAY, | ||||||||||||
3152 | "Outer class is an array class in class file %s", CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3153 | } | ||||||||||||
3154 | // Inner class name | ||||||||||||
3155 | const u2 inner_name_index = cfs->get_u2_fast(); | ||||||||||||
3156 | check_property( | ||||||||||||
3157 | inner_name_index == 0 || valid_symbol_at(inner_name_index), | ||||||||||||
3158 | "inner_name_index %u has bad constant type in class file %s", | ||||||||||||
3159 | inner_name_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3160 | if (_need_verify) { | ||||||||||||
3161 | guarantee_property(inner_class_info_index != outer_class_info_index, | ||||||||||||
3162 | "Class is both outer and inner class in class file %s", CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3163 | } | ||||||||||||
3164 | // Access flags | ||||||||||||
3165 | jint flags; | ||||||||||||
3166 | // JVM_ACC_MODULE is defined in JDK-9 and later. | ||||||||||||
3167 | if (_major_version >= JAVA_9_VERSION53) { | ||||||||||||
3168 | flags = cfs->get_u2_fast() & (RECOGNIZED_INNER_CLASS_MODIFIERS( (JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SUPER | JVM_ACC_INTERFACE | JVM_ACC_ABSTRACT | JVM_ACC_ANNOTATION | JVM_ACC_ENUM | JVM_ACC_SYNTHETIC ) | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC ) | JVM_ACC_MODULE); | ||||||||||||
3169 | } else { | ||||||||||||
3170 | flags = cfs->get_u2_fast() & RECOGNIZED_INNER_CLASS_MODIFIERS( (JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SUPER | JVM_ACC_INTERFACE | JVM_ACC_ABSTRACT | JVM_ACC_ANNOTATION | JVM_ACC_ENUM | JVM_ACC_SYNTHETIC ) | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC ); | ||||||||||||
3171 | } | ||||||||||||
3172 | if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION50) { | ||||||||||||
3173 | // Set abstract bit for old class files for backward compatibility | ||||||||||||
3174 | flags |= JVM_ACC_ABSTRACT; | ||||||||||||
3175 | } | ||||||||||||
3176 | verify_legal_class_modifiers(flags, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3177 | AccessFlags inner_access_flags(flags); | ||||||||||||
3178 | |||||||||||||
3179 | inner_classes->at_put(index++, inner_class_info_index); | ||||||||||||
3180 | inner_classes->at_put(index++, outer_class_info_index); | ||||||||||||
3181 | inner_classes->at_put(index++, inner_name_index); | ||||||||||||
3182 | inner_classes->at_put(index++, inner_access_flags.as_short()); | ||||||||||||
3183 | } | ||||||||||||
3184 | |||||||||||||
3185 | // 4347400: make sure there's no duplicate entry in the classes array | ||||||||||||
3186 | // Also, check for circular entries. | ||||||||||||
3187 | bool has_circularity = false; | ||||||||||||
3188 | if (_need_verify && _major_version >= JAVA_1_5_VERSION49) { | ||||||||||||
3189 | has_circularity = check_inner_classes_circularity(cp, length * 4, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3190 | if (has_circularity) { | ||||||||||||
3191 | // If circularity check failed then ignore InnerClasses attribute. | ||||||||||||
3192 | MetadataFactory::free_array<u2>(_loader_data, _inner_classes); | ||||||||||||
3193 | index = 0; | ||||||||||||
3194 | if (parsed_enclosingmethod_attribute) { | ||||||||||||
3195 | inner_classes = MetadataFactory::new_array<u2>(_loader_data, 2, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3196 | _inner_classes = inner_classes; | ||||||||||||
3197 | } else { | ||||||||||||
3198 | _inner_classes = Universe::the_empty_short_array(); | ||||||||||||
3199 | } | ||||||||||||
3200 | } | ||||||||||||
3201 | } | ||||||||||||
3202 | // Set EnclosingMethod class and method indexes. | ||||||||||||
3203 | if (parsed_enclosingmethod_attribute) { | ||||||||||||
3204 | inner_classes->at_put(index++, enclosing_method_class_index); | ||||||||||||
3205 | inner_classes->at_put(index++, enclosing_method_method_index); | ||||||||||||
3206 | } | ||||||||||||
3207 | assert(index == size || has_circularity, "wrong size")do { if (!(index == size || has_circularity)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3207, "assert(" "index == size || has_circularity" ") failed" , "wrong size"); ::breakpoint(); } } while (0); | ||||||||||||
3208 | |||||||||||||
3209 | // Restore buffer's current position. | ||||||||||||
3210 | cfs->set_current(current_mark); | ||||||||||||
3211 | |||||||||||||
3212 | return length; | ||||||||||||
3213 | } | ||||||||||||
3214 | |||||||||||||
3215 | u2 ClassFileParser::parse_classfile_nest_members_attribute(const ClassFileStream* const cfs, | ||||||||||||
3216 | const u1* const nest_members_attribute_start, | ||||||||||||
3217 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
3218 | const u1* const current_mark = cfs->current(); | ||||||||||||
3219 | u2 length = 0; | ||||||||||||
3220 | if (nest_members_attribute_start != NULL__null) { | ||||||||||||
3221 | cfs->set_current(nest_members_attribute_start); | ||||||||||||
3222 | cfs->guarantee_more(2, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); // length | ||||||||||||
3223 | length = cfs->get_u2_fast(); | ||||||||||||
3224 | } | ||||||||||||
3225 | const int size = length; | ||||||||||||
3226 | Array<u2>* const nest_members = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3227 | _nest_members = nest_members; | ||||||||||||
3228 | |||||||||||||
3229 | int index = 0; | ||||||||||||
3230 | cfs->guarantee_more(2 * length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3231 | for (int n = 0; n < length; n++) { | ||||||||||||
3232 | const u2 class_info_index = cfs->get_u2_fast(); | ||||||||||||
3233 | check_property( | ||||||||||||
3234 | valid_klass_reference_at(class_info_index), | ||||||||||||
3235 | "Nest member class_info_index %u has bad constant type in class file %s", | ||||||||||||
3236 | class_info_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3237 | nest_members->at_put(index++, class_info_index); | ||||||||||||
3238 | } | ||||||||||||
3239 | assert(index == size, "wrong size")do { if (!(index == size)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3239, "assert(" "index == size" ") failed", "wrong size"); :: breakpoint(); } } while (0); | ||||||||||||
3240 | |||||||||||||
3241 | // Restore buffer's current position. | ||||||||||||
3242 | cfs->set_current(current_mark); | ||||||||||||
3243 | |||||||||||||
3244 | return length; | ||||||||||||
3245 | } | ||||||||||||
3246 | |||||||||||||
3247 | u2 ClassFileParser::parse_classfile_permitted_subclasses_attribute(const ClassFileStream* const cfs, | ||||||||||||
3248 | const u1* const permitted_subclasses_attribute_start, | ||||||||||||
3249 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
3250 | const u1* const current_mark = cfs->current(); | ||||||||||||
3251 | u2 length = 0; | ||||||||||||
3252 | if (permitted_subclasses_attribute_start != NULL__null) { | ||||||||||||
3253 | cfs->set_current(permitted_subclasses_attribute_start); | ||||||||||||
3254 | cfs->guarantee_more(2, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); // length | ||||||||||||
3255 | length = cfs->get_u2_fast(); | ||||||||||||
3256 | } | ||||||||||||
3257 | const int size = length; | ||||||||||||
3258 | Array<u2>* const permitted_subclasses = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3259 | _permitted_subclasses = permitted_subclasses; | ||||||||||||
3260 | |||||||||||||
3261 | if (length > 0) { | ||||||||||||
3262 | int index = 0; | ||||||||||||
3263 | cfs->guarantee_more(2 * length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3264 | for (int n = 0; n < length; n++) { | ||||||||||||
3265 | const u2 class_info_index = cfs->get_u2_fast(); | ||||||||||||
3266 | check_property( | ||||||||||||
3267 | valid_klass_reference_at(class_info_index), | ||||||||||||
3268 | "Permitted subclass class_info_index %u has bad constant type in class file %s", | ||||||||||||
3269 | class_info_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3270 | permitted_subclasses->at_put(index++, class_info_index); | ||||||||||||
3271 | } | ||||||||||||
3272 | assert(index == size, "wrong size")do { if (!(index == size)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3272, "assert(" "index == size" ") failed", "wrong size"); :: breakpoint(); } } while (0); | ||||||||||||
3273 | } | ||||||||||||
3274 | |||||||||||||
3275 | // Restore buffer's current position. | ||||||||||||
3276 | cfs->set_current(current_mark); | ||||||||||||
3277 | |||||||||||||
3278 | return length; | ||||||||||||
3279 | } | ||||||||||||
3280 | |||||||||||||
3281 | // Record { | ||||||||||||
3282 | // u2 attribute_name_index; | ||||||||||||
3283 | // u4 attribute_length; | ||||||||||||
3284 | // u2 components_count; | ||||||||||||
3285 | // component_info components[components_count]; | ||||||||||||
3286 | // } | ||||||||||||
3287 | // component_info { | ||||||||||||
3288 | // u2 name_index; | ||||||||||||
3289 | // u2 descriptor_index | ||||||||||||
3290 | // u2 attributes_count; | ||||||||||||
3291 | // attribute_info_attributes[attributes_count]; | ||||||||||||
3292 | // } | ||||||||||||
3293 | u2 ClassFileParser::parse_classfile_record_attribute(const ClassFileStream* const cfs, | ||||||||||||
3294 | const ConstantPool* cp, | ||||||||||||
3295 | const u1* const record_attribute_start, | ||||||||||||
3296 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
3297 | const u1* const current_mark = cfs->current(); | ||||||||||||
3298 | int components_count = 0; | ||||||||||||
3299 | unsigned int calculate_attr_size = 0; | ||||||||||||
3300 | if (record_attribute_start != NULL__null) { | ||||||||||||
3301 | cfs->set_current(record_attribute_start); | ||||||||||||
3302 | cfs->guarantee_more(2, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); // num of components | ||||||||||||
3303 | components_count = (int)cfs->get_u2_fast(); | ||||||||||||
3304 | calculate_attr_size = 2; | ||||||||||||
3305 | } | ||||||||||||
3306 | |||||||||||||
3307 | Array<RecordComponent*>* const record_components = | ||||||||||||
3308 | MetadataFactory::new_array<RecordComponent*>(_loader_data, components_count, NULL__null, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3309 | _record_components = record_components; | ||||||||||||
3310 | |||||||||||||
3311 | for (int x = 0; x < components_count; x++) { | ||||||||||||
3312 | cfs->guarantee_more(6, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); // name_index, descriptor_index, attributes_count | ||||||||||||
3313 | |||||||||||||
3314 | const u2 name_index = cfs->get_u2_fast(); | ||||||||||||
3315 | check_property(valid_symbol_at(name_index), | ||||||||||||
3316 | "Invalid constant pool index %u for name in Record attribute in class file %s", | ||||||||||||
3317 | name_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3318 | const Symbol* const name = cp->symbol_at(name_index); | ||||||||||||
3319 | verify_legal_field_name(name, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3320 | |||||||||||||
3321 | const u2 descriptor_index = cfs->get_u2_fast(); | ||||||||||||
3322 | check_property(valid_symbol_at(descriptor_index), | ||||||||||||
3323 | "Invalid constant pool index %u for descriptor in Record attribute in class file %s", | ||||||||||||
3324 | descriptor_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3325 | const Symbol* const descr = cp->symbol_at(descriptor_index); | ||||||||||||
3326 | verify_legal_field_signature(name, descr, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3327 | |||||||||||||
3328 | const u2 attributes_count = cfs->get_u2_fast(); | ||||||||||||
3329 | calculate_attr_size += 6; | ||||||||||||
3330 | u2 generic_sig_index = 0; | ||||||||||||
3331 | const u1* runtime_visible_annotations = NULL__null; | ||||||||||||
3332 | int runtime_visible_annotations_length = 0; | ||||||||||||
3333 | const u1* runtime_invisible_annotations = NULL__null; | ||||||||||||
3334 | int runtime_invisible_annotations_length = 0; | ||||||||||||
3335 | bool runtime_invisible_annotations_exists = false; | ||||||||||||
3336 | const u1* runtime_visible_type_annotations = NULL__null; | ||||||||||||
3337 | int runtime_visible_type_annotations_length = 0; | ||||||||||||
3338 | const u1* runtime_invisible_type_annotations = NULL__null; | ||||||||||||
3339 | int runtime_invisible_type_annotations_length = 0; | ||||||||||||
3340 | bool runtime_invisible_type_annotations_exists = false; | ||||||||||||
3341 | |||||||||||||
3342 | // Expected attributes for record components are Signature, Runtime(In)VisibleAnnotations, | ||||||||||||
3343 | // and Runtime(In)VisibleTypeAnnotations. Other attributes are ignored. | ||||||||||||
3344 | for (int y = 0; y < attributes_count; y++) { | ||||||||||||
3345 | cfs->guarantee_more(6, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); // attribute_name_index, attribute_length | ||||||||||||
3346 | const u2 attribute_name_index = cfs->get_u2_fast(); | ||||||||||||
3347 | const u4 attribute_length = cfs->get_u4_fast(); | ||||||||||||
3348 | calculate_attr_size += 6; | ||||||||||||
3349 | check_property( | ||||||||||||
3350 | valid_symbol_at(attribute_name_index), | ||||||||||||
3351 | "Invalid Record attribute name index %u in class file %s", | ||||||||||||
3352 | attribute_name_index, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3353 | |||||||||||||
3354 | const Symbol* const attribute_name = cp->symbol_at(attribute_name_index); | ||||||||||||
3355 | if (attribute_name == vmSymbols::tag_signature()) { | ||||||||||||
3356 | if (generic_sig_index != 0) { | ||||||||||||
3357 | classfile_parse_error( | ||||||||||||
3358 | "Multiple Signature attributes for Record component in class file %s", | ||||||||||||
3359 | THREAD__the_thread__); | ||||||||||||
3360 | return 0; | ||||||||||||
3361 | } | ||||||||||||
3362 | if (attribute_length != 2) { | ||||||||||||
3363 | classfile_parse_error( | ||||||||||||
3364 | "Invalid Signature attribute length %u in Record component in class file %s", | ||||||||||||
3365 | attribute_length, THREAD__the_thread__); | ||||||||||||
3366 | return 0; | ||||||||||||
3367 | } | ||||||||||||
3368 | generic_sig_index = parse_generic_signature_attribute(cfs, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3369 | |||||||||||||
3370 | } else if (attribute_name == vmSymbols::tag_runtime_visible_annotations()) { | ||||||||||||
3371 | if (runtime_visible_annotations != NULL__null) { | ||||||||||||
3372 | classfile_parse_error( | ||||||||||||
3373 | "Multiple RuntimeVisibleAnnotations attributes for Record component in class file %s", THREAD__the_thread__); | ||||||||||||
3374 | return 0; | ||||||||||||
3375 | } | ||||||||||||
3376 | runtime_visible_annotations_length = attribute_length; | ||||||||||||
3377 | runtime_visible_annotations = cfs->current(); | ||||||||||||
3378 | |||||||||||||
3379 | assert(runtime_visible_annotations != NULL, "null record component visible annotation")do { if (!(runtime_visible_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3379, "assert(" "runtime_visible_annotations != __null" ") failed" , "null record component visible annotation"); ::breakpoint() ; } } while (0); | ||||||||||||
3380 | cfs->guarantee_more(runtime_visible_annotations_length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3381 | cfs->skip_u1_fast(runtime_visible_annotations_length); | ||||||||||||
3382 | |||||||||||||
3383 | } else if (attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { | ||||||||||||
3384 | if (runtime_invisible_annotations_exists) { | ||||||||||||
3385 | classfile_parse_error( | ||||||||||||
3386 | "Multiple RuntimeInvisibleAnnotations attributes for Record component in class file %s", THREAD__the_thread__); | ||||||||||||
3387 | return 0; | ||||||||||||
3388 | } | ||||||||||||
3389 | runtime_invisible_annotations_exists = true; | ||||||||||||
3390 | if (PreserveAllAnnotations) { | ||||||||||||
3391 | runtime_invisible_annotations_length = attribute_length; | ||||||||||||
3392 | runtime_invisible_annotations = cfs->current(); | ||||||||||||
3393 | assert(runtime_invisible_annotations != NULL, "null record component invisible annotation")do { if (!(runtime_invisible_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3393, "assert(" "runtime_invisible_annotations != __null" ") failed" , "null record component invisible annotation"); ::breakpoint (); } } while (0); | ||||||||||||
3394 | } | ||||||||||||
3395 | cfs->skip_u1(attribute_length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3396 | |||||||||||||
3397 | } else if (attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) { | ||||||||||||
3398 | if (runtime_visible_type_annotations != NULL__null) { | ||||||||||||
3399 | classfile_parse_error( | ||||||||||||
3400 | "Multiple RuntimeVisibleTypeAnnotations attributes for Record component in class file %s", THREAD__the_thread__); | ||||||||||||
3401 | return 0; | ||||||||||||
3402 | } | ||||||||||||
3403 | runtime_visible_type_annotations_length = attribute_length; | ||||||||||||
3404 | runtime_visible_type_annotations = cfs->current(); | ||||||||||||
3405 | |||||||||||||
3406 | assert(runtime_visible_type_annotations != NULL, "null record component visible type annotation")do { if (!(runtime_visible_type_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3406, "assert(" "runtime_visible_type_annotations != __null" ") failed", "null record component visible type annotation") ; ::breakpoint(); } } while (0); | ||||||||||||
3407 | cfs->guarantee_more(runtime_visible_type_annotations_length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3408 | cfs->skip_u1_fast(runtime_visible_type_annotations_length); | ||||||||||||
3409 | |||||||||||||
3410 | } else if (attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) { | ||||||||||||
3411 | if (runtime_invisible_type_annotations_exists) { | ||||||||||||
3412 | classfile_parse_error( | ||||||||||||
3413 | "Multiple RuntimeInvisibleTypeAnnotations attributes for Record component in class file %s", THREAD__the_thread__); | ||||||||||||
3414 | return 0; | ||||||||||||
3415 | } | ||||||||||||
3416 | runtime_invisible_type_annotations_exists = true; | ||||||||||||
3417 | if (PreserveAllAnnotations) { | ||||||||||||
3418 | runtime_invisible_type_annotations_length = attribute_length; | ||||||||||||
3419 | runtime_invisible_type_annotations = cfs->current(); | ||||||||||||
3420 | assert(runtime_invisible_type_annotations != NULL, "null record component invisible type annotation")do { if (!(runtime_invisible_type_annotations != __null)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3420, "assert(" "runtime_invisible_type_annotations != __null" ") failed", "null record component invisible type annotation" ); ::breakpoint(); } } while (0); | ||||||||||||
3421 | } | ||||||||||||
3422 | cfs->skip_u1(attribute_length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3423 | |||||||||||||
3424 | } else { | ||||||||||||
3425 | // Skip unknown attributes | ||||||||||||
3426 | cfs->skip_u1(attribute_length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3427 | } | ||||||||||||
3428 | calculate_attr_size += attribute_length; | ||||||||||||
3429 | } // End of attributes For loop | ||||||||||||
3430 | |||||||||||||
3431 | AnnotationArray* annotations = assemble_annotations(runtime_visible_annotations, | ||||||||||||
3432 | runtime_visible_annotations_length, | ||||||||||||
3433 | runtime_invisible_annotations, | ||||||||||||
3434 | runtime_invisible_annotations_length, | ||||||||||||
3435 | CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3436 | AnnotationArray* type_annotations = assemble_annotations(runtime_visible_type_annotations, | ||||||||||||
3437 | runtime_visible_type_annotations_length, | ||||||||||||
3438 | runtime_invisible_type_annotations, | ||||||||||||
3439 | runtime_invisible_type_annotations_length, | ||||||||||||
3440 | CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3441 | |||||||||||||
3442 | RecordComponent* record_component = | ||||||||||||
3443 | RecordComponent::allocate(_loader_data, name_index, descriptor_index, | ||||||||||||
3444 | attributes_count, generic_sig_index, | ||||||||||||
3445 | annotations, type_annotations, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
3446 | record_components->at_put(x, record_component); | ||||||||||||
3447 | } // End of component processing loop | ||||||||||||
3448 | |||||||||||||
3449 | // Restore buffer's current position. | ||||||||||||
3450 | cfs->set_current(current_mark); | ||||||||||||
3451 | return calculate_attr_size; | ||||||||||||
3452 | } | ||||||||||||
3453 | |||||||||||||
3454 | void ClassFileParser::parse_classfile_synthetic_attribute() { | ||||||||||||
3455 | set_class_synthetic_flag(true); | ||||||||||||
3456 | } | ||||||||||||
3457 | |||||||||||||
3458 | void ClassFileParser::parse_classfile_signature_attribute(const ClassFileStream* const cfs, TRAPSJavaThread* __the_thread__) { | ||||||||||||
3459 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3459, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
3460 | |||||||||||||
3461 | const u2 signature_index = cfs->get_u2(CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3462 | check_property( | ||||||||||||
3463 | valid_symbol_at(signature_index), | ||||||||||||
3464 | "Invalid constant pool index %u in Signature attribute in class file %s", | ||||||||||||
3465 | signature_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3466 | set_class_generic_signature_index(signature_index); | ||||||||||||
3467 | } | ||||||||||||
3468 | |||||||||||||
3469 | void ClassFileParser::parse_classfile_bootstrap_methods_attribute(const ClassFileStream* const cfs, | ||||||||||||
3470 | ConstantPool* cp, | ||||||||||||
3471 | u4 attribute_byte_length, | ||||||||||||
3472 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
3473 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3473, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
3474 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3474, "assert(" "cp != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
3475 | |||||||||||||
3476 | const u1* const current_start = cfs->current(); | ||||||||||||
3477 | |||||||||||||
3478 | guarantee_property(attribute_byte_length >= sizeof(u2), | ||||||||||||
3479 | "Invalid BootstrapMethods attribute length %u in class file %s", | ||||||||||||
3480 | attribute_byte_length, | ||||||||||||
3481 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3482 | |||||||||||||
3483 | cfs->guarantee_more(attribute_byte_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3484 | |||||||||||||
3485 | const int attribute_array_length = cfs->get_u2_fast(); | ||||||||||||
3486 | |||||||||||||
3487 | guarantee_property(_max_bootstrap_specifier_index < attribute_array_length, | ||||||||||||
3488 | "Short length on BootstrapMethods in class file %s", | ||||||||||||
3489 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3490 | |||||||||||||
3491 | |||||||||||||
3492 | // The attribute contains a counted array of counted tuples of shorts, | ||||||||||||
3493 | // represending bootstrap specifiers: | ||||||||||||
3494 | // length*{bootstrap_method_index, argument_count*{argument_index}} | ||||||||||||
3495 | const int operand_count = (attribute_byte_length - sizeof(u2)) / sizeof(u2); | ||||||||||||
3496 | // operand_count = number of shorts in attr, except for leading length | ||||||||||||
3497 | |||||||||||||
3498 | // The attribute is copied into a short[] array. | ||||||||||||
3499 | // The array begins with a series of short[2] pairs, one for each tuple. | ||||||||||||
3500 | const int index_size = (attribute_array_length * 2); | ||||||||||||
3501 | |||||||||||||
3502 | Array<u2>* const operands = | ||||||||||||
3503 | MetadataFactory::new_array<u2>(_loader_data, index_size + operand_count, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3504 | |||||||||||||
3505 | // Eagerly assign operands so they will be deallocated with the constant | ||||||||||||
3506 | // pool if there is an error. | ||||||||||||
3507 | cp->set_operands(operands); | ||||||||||||
3508 | |||||||||||||
3509 | int operand_fill_index = index_size; | ||||||||||||
3510 | const int cp_size = cp->length(); | ||||||||||||
3511 | |||||||||||||
3512 | for (int n = 0; n < attribute_array_length; n++) { | ||||||||||||
3513 | // Store a 32-bit offset into the header of the operand array. | ||||||||||||
3514 | ConstantPool::operand_offset_at_put(operands, n, operand_fill_index); | ||||||||||||
3515 | |||||||||||||
3516 | // Read a bootstrap specifier. | ||||||||||||
3517 | cfs->guarantee_more(sizeof(u2) * 2, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // bsm, argc | ||||||||||||
3518 | const u2 bootstrap_method_index = cfs->get_u2_fast(); | ||||||||||||
3519 | const u2 argument_count = cfs->get_u2_fast(); | ||||||||||||
3520 | check_property( | ||||||||||||
3521 | valid_cp_range(bootstrap_method_index, cp_size) && | ||||||||||||
3522 | cp->tag_at(bootstrap_method_index).is_method_handle(), | ||||||||||||
3523 | "bootstrap_method_index %u has bad constant type in class file %s", | ||||||||||||
3524 | bootstrap_method_index, | ||||||||||||
3525 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3526 | |||||||||||||
3527 | guarantee_property((operand_fill_index + 1 + argument_count) < operands->length(), | ||||||||||||
3528 | "Invalid BootstrapMethods num_bootstrap_methods or num_bootstrap_arguments value in class file %s", | ||||||||||||
3529 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3530 | |||||||||||||
3531 | operands->at_put(operand_fill_index++, bootstrap_method_index); | ||||||||||||
3532 | operands->at_put(operand_fill_index++, argument_count); | ||||||||||||
3533 | |||||||||||||
3534 | cfs->guarantee_more(sizeof(u2) * argument_count, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // argv[argc] | ||||||||||||
3535 | for (int j = 0; j < argument_count; j++) { | ||||||||||||
3536 | const u2 argument_index = cfs->get_u2_fast(); | ||||||||||||
3537 | check_property( | ||||||||||||
3538 | valid_cp_range(argument_index, cp_size) && | ||||||||||||
3539 | cp->tag_at(argument_index).is_loadable_constant(), | ||||||||||||
3540 | "argument_index %u has bad constant type in class file %s", | ||||||||||||
3541 | argument_index, | ||||||||||||
3542 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3543 | operands->at_put(operand_fill_index++, argument_index); | ||||||||||||
3544 | } | ||||||||||||
3545 | } | ||||||||||||
3546 | guarantee_property(current_start + attribute_byte_length == cfs->current(), | ||||||||||||
3547 | "Bad length on BootstrapMethods in class file %s", | ||||||||||||
3548 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3549 | } | ||||||||||||
3550 | |||||||||||||
3551 | void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cfs, | ||||||||||||
3552 | ConstantPool* cp, | ||||||||||||
3553 | ClassFileParser::ClassAnnotationCollector* parsed_annotations, | ||||||||||||
3554 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
3555 | assert(cfs != NULL, "invariant")do { if (!(cfs != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3555, "assert(" "cfs != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
3556 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3556, "assert(" "cp != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
3557 | assert(parsed_annotations != NULL, "invariant")do { if (!(parsed_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3557, "assert(" "parsed_annotations != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
3558 | |||||||||||||
3559 | // Set inner classes attribute to default sentinel | ||||||||||||
3560 | _inner_classes = Universe::the_empty_short_array(); | ||||||||||||
3561 | // Set nest members attribute to default sentinel | ||||||||||||
3562 | _nest_members = Universe::the_empty_short_array(); | ||||||||||||
3563 | // Set _permitted_subclasses attribute to default sentinel | ||||||||||||
3564 | _permitted_subclasses = Universe::the_empty_short_array(); | ||||||||||||
3565 | cfs->guarantee_more(2, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // attributes_count | ||||||||||||
3566 | u2 attributes_count = cfs->get_u2_fast(); | ||||||||||||
3567 | bool parsed_sourcefile_attribute = false; | ||||||||||||
3568 | bool parsed_innerclasses_attribute = false; | ||||||||||||
3569 | bool parsed_nest_members_attribute = false; | ||||||||||||
3570 | bool parsed_permitted_subclasses_attribute = false; | ||||||||||||
3571 | bool parsed_nest_host_attribute = false; | ||||||||||||
3572 | bool parsed_record_attribute = false; | ||||||||||||
3573 | bool parsed_enclosingmethod_attribute = false; | ||||||||||||
3574 | bool parsed_bootstrap_methods_attribute = false; | ||||||||||||
3575 | const u1* runtime_visible_annotations = NULL__null; | ||||||||||||
3576 | int runtime_visible_annotations_length = 0; | ||||||||||||
3577 | const u1* runtime_invisible_annotations = NULL__null; | ||||||||||||
3578 | int runtime_invisible_annotations_length = 0; | ||||||||||||
3579 | const u1* runtime_visible_type_annotations = NULL__null; | ||||||||||||
3580 | int runtime_visible_type_annotations_length = 0; | ||||||||||||
3581 | const u1* runtime_invisible_type_annotations = NULL__null; | ||||||||||||
3582 | int runtime_invisible_type_annotations_length = 0; | ||||||||||||
3583 | bool runtime_invisible_type_annotations_exists = false; | ||||||||||||
3584 | bool runtime_invisible_annotations_exists = false; | ||||||||||||
3585 | bool parsed_source_debug_ext_annotations_exist = false; | ||||||||||||
3586 | const u1* inner_classes_attribute_start = NULL__null; | ||||||||||||
3587 | u4 inner_classes_attribute_length = 0; | ||||||||||||
3588 | u2 enclosing_method_class_index = 0; | ||||||||||||
3589 | u2 enclosing_method_method_index = 0; | ||||||||||||
3590 | const u1* nest_members_attribute_start = NULL__null; | ||||||||||||
3591 | u4 nest_members_attribute_length = 0; | ||||||||||||
3592 | const u1* record_attribute_start = NULL__null; | ||||||||||||
3593 | u4 record_attribute_length = 0; | ||||||||||||
3594 | const u1* permitted_subclasses_attribute_start = NULL__null; | ||||||||||||
3595 | u4 permitted_subclasses_attribute_length = 0; | ||||||||||||
3596 | |||||||||||||
3597 | // Iterate over attributes | ||||||||||||
3598 | while (attributes_count--) { | ||||||||||||
3599 | cfs->guarantee_more(6, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // attribute_name_index, attribute_length | ||||||||||||
3600 | const u2 attribute_name_index = cfs->get_u2_fast(); | ||||||||||||
3601 | const u4 attribute_length = cfs->get_u4_fast(); | ||||||||||||
3602 | check_property( | ||||||||||||
3603 | valid_symbol_at(attribute_name_index), | ||||||||||||
3604 | "Attribute name has bad constant pool index %u in class file %s", | ||||||||||||
3605 | attribute_name_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3606 | const Symbol* const tag = cp->symbol_at(attribute_name_index); | ||||||||||||
3607 | if (tag == vmSymbols::tag_source_file()) { | ||||||||||||
3608 | // Check for SourceFile tag | ||||||||||||
3609 | if (_need_verify) { | ||||||||||||
3610 | guarantee_property(attribute_length == 2, "Wrong SourceFile attribute length in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3611 | } | ||||||||||||
3612 | if (parsed_sourcefile_attribute) { | ||||||||||||
3613 | classfile_parse_error("Multiple SourceFile attributes in class file %s", THREAD__the_thread__); | ||||||||||||
3614 | return; | ||||||||||||
3615 | } else { | ||||||||||||
3616 | parsed_sourcefile_attribute = true; | ||||||||||||
3617 | } | ||||||||||||
3618 | parse_classfile_sourcefile_attribute(cfs, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3619 | } else if (tag == vmSymbols::tag_source_debug_extension()) { | ||||||||||||
3620 | // Check for SourceDebugExtension tag | ||||||||||||
3621 | if (parsed_source_debug_ext_annotations_exist) { | ||||||||||||
3622 | classfile_parse_error( | ||||||||||||
3623 | "Multiple SourceDebugExtension attributes in class file %s", THREAD__the_thread__); | ||||||||||||
3624 | return; | ||||||||||||
3625 | } | ||||||||||||
3626 | parsed_source_debug_ext_annotations_exist = true; | ||||||||||||
3627 | parse_classfile_source_debug_extension_attribute(cfs, (int)attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3628 | } else if (tag == vmSymbols::tag_inner_classes()) { | ||||||||||||
3629 | // Check for InnerClasses tag | ||||||||||||
3630 | if (parsed_innerclasses_attribute) { | ||||||||||||
3631 | classfile_parse_error("Multiple InnerClasses attributes in class file %s", THREAD__the_thread__); | ||||||||||||
3632 | return; | ||||||||||||
3633 | } else { | ||||||||||||
3634 | parsed_innerclasses_attribute = true; | ||||||||||||
3635 | } | ||||||||||||
3636 | inner_classes_attribute_start = cfs->current(); | ||||||||||||
3637 | inner_classes_attribute_length = attribute_length; | ||||||||||||
3638 | cfs->skip_u1(inner_classes_attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3639 | } else if (tag == vmSymbols::tag_synthetic()) { | ||||||||||||
3640 | // Check for Synthetic tag | ||||||||||||
3641 | // Shouldn't we check that the synthetic flags wasn't already set? - not required in spec | ||||||||||||
3642 | if (attribute_length != 0) { | ||||||||||||
3643 | classfile_parse_error( | ||||||||||||
3644 | "Invalid Synthetic classfile attribute length %u in class file %s", | ||||||||||||
3645 | attribute_length, THREAD__the_thread__); | ||||||||||||
3646 | return; | ||||||||||||
3647 | } | ||||||||||||
3648 | parse_classfile_synthetic_attribute(); | ||||||||||||
3649 | } else if (tag == vmSymbols::tag_deprecated()) { | ||||||||||||
3650 | // Check for Deprecated tag - 4276120 | ||||||||||||
3651 | if (attribute_length != 0) { | ||||||||||||
3652 | classfile_parse_error( | ||||||||||||
3653 | "Invalid Deprecated classfile attribute length %u in class file %s", | ||||||||||||
3654 | attribute_length, THREAD__the_thread__); | ||||||||||||
3655 | return; | ||||||||||||
3656 | } | ||||||||||||
3657 | } else if (_major_version >= JAVA_1_5_VERSION49) { | ||||||||||||
3658 | if (tag == vmSymbols::tag_signature()) { | ||||||||||||
3659 | if (_generic_signature_index != 0) { | ||||||||||||
3660 | classfile_parse_error( | ||||||||||||
3661 | "Multiple Signature attributes in class file %s", THREAD__the_thread__); | ||||||||||||
3662 | return; | ||||||||||||
3663 | } | ||||||||||||
3664 | if (attribute_length != 2) { | ||||||||||||
3665 | classfile_parse_error( | ||||||||||||
3666 | "Wrong Signature attribute length %u in class file %s", | ||||||||||||
3667 | attribute_length, THREAD__the_thread__); | ||||||||||||
3668 | return; | ||||||||||||
3669 | } | ||||||||||||
3670 | parse_classfile_signature_attribute(cfs, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3671 | } else if (tag == vmSymbols::tag_runtime_visible_annotations()) { | ||||||||||||
3672 | if (runtime_visible_annotations != NULL__null) { | ||||||||||||
3673 | classfile_parse_error( | ||||||||||||
3674 | "Multiple RuntimeVisibleAnnotations attributes in class file %s", THREAD__the_thread__); | ||||||||||||
3675 | return; | ||||||||||||
3676 | } | ||||||||||||
3677 | runtime_visible_annotations_length = attribute_length; | ||||||||||||
3678 | runtime_visible_annotations = cfs->current(); | ||||||||||||
3679 | assert(runtime_visible_annotations != NULL, "null visible annotations")do { if (!(runtime_visible_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3679, "assert(" "runtime_visible_annotations != __null" ") failed" , "null visible annotations"); ::breakpoint(); } } while (0); | ||||||||||||
3680 | cfs->guarantee_more(runtime_visible_annotations_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3681 | parse_annotations(cp, | ||||||||||||
3682 | runtime_visible_annotations, | ||||||||||||
3683 | runtime_visible_annotations_length, | ||||||||||||
3684 | parsed_annotations, | ||||||||||||
3685 | _loader_data, | ||||||||||||
3686 | _can_access_vm_annotations); | ||||||||||||
3687 | cfs->skip_u1_fast(runtime_visible_annotations_length); | ||||||||||||
3688 | } else if (tag == vmSymbols::tag_runtime_invisible_annotations()) { | ||||||||||||
3689 | if (runtime_invisible_annotations_exists) { | ||||||||||||
3690 | classfile_parse_error( | ||||||||||||
3691 | "Multiple RuntimeInvisibleAnnotations attributes in class file %s", THREAD__the_thread__); | ||||||||||||
3692 | return; | ||||||||||||
3693 | } | ||||||||||||
3694 | runtime_invisible_annotations_exists = true; | ||||||||||||
3695 | if (PreserveAllAnnotations) { | ||||||||||||
3696 | runtime_invisible_annotations_length = attribute_length; | ||||||||||||
3697 | runtime_invisible_annotations = cfs->current(); | ||||||||||||
3698 | assert(runtime_invisible_annotations != NULL, "null invisible annotations")do { if (!(runtime_invisible_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3698, "assert(" "runtime_invisible_annotations != __null" ") failed" , "null invisible annotations"); ::breakpoint(); } } while (0 ); | ||||||||||||
3699 | } | ||||||||||||
3700 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3701 | } else if (tag == vmSymbols::tag_enclosing_method()) { | ||||||||||||
3702 | if (parsed_enclosingmethod_attribute) { | ||||||||||||
3703 | classfile_parse_error("Multiple EnclosingMethod attributes in class file %s", THREAD__the_thread__); | ||||||||||||
3704 | return; | ||||||||||||
3705 | } else { | ||||||||||||
3706 | parsed_enclosingmethod_attribute = true; | ||||||||||||
3707 | } | ||||||||||||
3708 | guarantee_property(attribute_length == 4, | ||||||||||||
3709 | "Wrong EnclosingMethod attribute length %u in class file %s", | ||||||||||||
3710 | attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3711 | cfs->guarantee_more(4, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // class_index, method_index | ||||||||||||
3712 | enclosing_method_class_index = cfs->get_u2_fast(); | ||||||||||||
3713 | enclosing_method_method_index = cfs->get_u2_fast(); | ||||||||||||
3714 | if (enclosing_method_class_index == 0) { | ||||||||||||
3715 | classfile_parse_error("Invalid class index in EnclosingMethod attribute in class file %s", THREAD__the_thread__); | ||||||||||||
3716 | return; | ||||||||||||
3717 | } | ||||||||||||
3718 | // Validate the constant pool indices and types | ||||||||||||
3719 | check_property(valid_klass_reference_at(enclosing_method_class_index), | ||||||||||||
3720 | "Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3721 | if (enclosing_method_method_index != 0 && | ||||||||||||
3722 | (!cp->is_within_bounds(enclosing_method_method_index) || | ||||||||||||
3723 | !cp->tag_at(enclosing_method_method_index).is_name_and_type())) { | ||||||||||||
3724 | classfile_parse_error("Invalid or out-of-bounds method index in EnclosingMethod attribute in class file %s", THREAD__the_thread__); | ||||||||||||
3725 | return; | ||||||||||||
3726 | } | ||||||||||||
3727 | } else if (tag == vmSymbols::tag_bootstrap_methods() && | ||||||||||||
3728 | _major_version >= Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { | ||||||||||||
3729 | if (parsed_bootstrap_methods_attribute) { | ||||||||||||
3730 | classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", THREAD__the_thread__); | ||||||||||||
3731 | return; | ||||||||||||
3732 | } | ||||||||||||
3733 | parsed_bootstrap_methods_attribute = true; | ||||||||||||
3734 | parse_classfile_bootstrap_methods_attribute(cfs, cp, attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3735 | } else if (tag == vmSymbols::tag_runtime_visible_type_annotations()) { | ||||||||||||
3736 | if (runtime_visible_type_annotations != NULL__null) { | ||||||||||||
3737 | classfile_parse_error( | ||||||||||||
3738 | "Multiple RuntimeVisibleTypeAnnotations attributes in class file %s", THREAD__the_thread__); | ||||||||||||
3739 | return; | ||||||||||||
3740 | } | ||||||||||||
3741 | runtime_visible_type_annotations_length = attribute_length; | ||||||||||||
3742 | runtime_visible_type_annotations = cfs->current(); | ||||||||||||
3743 | assert(runtime_visible_type_annotations != NULL, "null visible type annotations")do { if (!(runtime_visible_type_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3743, "assert(" "runtime_visible_type_annotations != __null" ") failed", "null visible type annotations"); ::breakpoint() ; } } while (0); | ||||||||||||
3744 | // No need for the VM to parse Type annotations | ||||||||||||
3745 | cfs->skip_u1(runtime_visible_type_annotations_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3746 | } else if (tag == vmSymbols::tag_runtime_invisible_type_annotations()) { | ||||||||||||
3747 | if (runtime_invisible_type_annotations_exists) { | ||||||||||||
3748 | classfile_parse_error( | ||||||||||||
3749 | "Multiple RuntimeInvisibleTypeAnnotations attributes in class file %s", THREAD__the_thread__); | ||||||||||||
3750 | return; | ||||||||||||
3751 | } else { | ||||||||||||
3752 | runtime_invisible_type_annotations_exists = true; | ||||||||||||
3753 | } | ||||||||||||
3754 | if (PreserveAllAnnotations) { | ||||||||||||
3755 | runtime_invisible_type_annotations_length = attribute_length; | ||||||||||||
3756 | runtime_invisible_type_annotations = cfs->current(); | ||||||||||||
3757 | assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations")do { if (!(runtime_invisible_type_annotations != __null)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3757, "assert(" "runtime_invisible_type_annotations != __null" ") failed", "null invisible type annotations"); ::breakpoint (); } } while (0); | ||||||||||||
3758 | } | ||||||||||||
3759 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3760 | } else if (_major_version >= JAVA_11_VERSION55) { | ||||||||||||
3761 | if (tag == vmSymbols::tag_nest_members()) { | ||||||||||||
3762 | // Check for NestMembers tag | ||||||||||||
3763 | if (parsed_nest_members_attribute) { | ||||||||||||
3764 | classfile_parse_error("Multiple NestMembers attributes in class file %s", THREAD__the_thread__); | ||||||||||||
3765 | return; | ||||||||||||
3766 | } else { | ||||||||||||
3767 | parsed_nest_members_attribute = true; | ||||||||||||
3768 | } | ||||||||||||
3769 | if (parsed_nest_host_attribute) { | ||||||||||||
3770 | classfile_parse_error("Conflicting NestHost and NestMembers attributes in class file %s", THREAD__the_thread__); | ||||||||||||
3771 | return; | ||||||||||||
3772 | } | ||||||||||||
3773 | nest_members_attribute_start = cfs->current(); | ||||||||||||
3774 | nest_members_attribute_length = attribute_length; | ||||||||||||
3775 | cfs->skip_u1(nest_members_attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3776 | } else if (tag == vmSymbols::tag_nest_host()) { | ||||||||||||
3777 | if (parsed_nest_host_attribute) { | ||||||||||||
3778 | classfile_parse_error("Multiple NestHost attributes in class file %s", THREAD__the_thread__); | ||||||||||||
3779 | return; | ||||||||||||
3780 | } else { | ||||||||||||
3781 | parsed_nest_host_attribute = true; | ||||||||||||
3782 | } | ||||||||||||
3783 | if (parsed_nest_members_attribute) { | ||||||||||||
3784 | classfile_parse_error("Conflicting NestMembers and NestHost attributes in class file %s", THREAD__the_thread__); | ||||||||||||
3785 | return; | ||||||||||||
3786 | } | ||||||||||||
3787 | if (_need_verify) { | ||||||||||||
3788 | guarantee_property(attribute_length == 2, "Wrong NestHost attribute length in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3789 | } | ||||||||||||
3790 | cfs->guarantee_more(2, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3791 | u2 class_info_index = cfs->get_u2_fast(); | ||||||||||||
3792 | check_property( | ||||||||||||
3793 | valid_klass_reference_at(class_info_index), | ||||||||||||
3794 | "Nest-host class_info_index %u has bad constant type in class file %s", | ||||||||||||
3795 | class_info_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3796 | _nest_host = class_info_index; | ||||||||||||
3797 | |||||||||||||
3798 | } else if (_major_version >= JAVA_16_VERSION60) { | ||||||||||||
3799 | if (tag == vmSymbols::tag_record()) { | ||||||||||||
3800 | if (parsed_record_attribute) { | ||||||||||||
3801 | classfile_parse_error("Multiple Record attributes in class file %s", THREAD__the_thread__); | ||||||||||||
3802 | return; | ||||||||||||
3803 | } | ||||||||||||
3804 | parsed_record_attribute = true; | ||||||||||||
3805 | record_attribute_start = cfs->current(); | ||||||||||||
3806 | record_attribute_length = attribute_length; | ||||||||||||
3807 | } else if (_major_version >= JAVA_17_VERSION61) { | ||||||||||||
3808 | if (tag == vmSymbols::tag_permitted_subclasses()) { | ||||||||||||
3809 | if (parsed_permitted_subclasses_attribute) { | ||||||||||||
3810 | classfile_parse_error("Multiple PermittedSubclasses attributes in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3811 | return; | ||||||||||||
3812 | } | ||||||||||||
3813 | // Classes marked ACC_FINAL cannot have a PermittedSubclasses attribute. | ||||||||||||
3814 | if (_access_flags.is_final()) { | ||||||||||||
3815 | classfile_parse_error("PermittedSubclasses attribute in final class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3816 | return; | ||||||||||||
3817 | } | ||||||||||||
3818 | parsed_permitted_subclasses_attribute = true; | ||||||||||||
3819 | permitted_subclasses_attribute_start = cfs->current(); | ||||||||||||
3820 | permitted_subclasses_attribute_length = attribute_length; | ||||||||||||
3821 | } | ||||||||||||
3822 | } | ||||||||||||
3823 | // Skip attribute_length for any attribute where major_verson >= JAVA_17_VERSION | ||||||||||||
3824 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3825 | } else { | ||||||||||||
3826 | // Unknown attribute | ||||||||||||
3827 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3828 | } | ||||||||||||
3829 | } else { | ||||||||||||
3830 | // Unknown attribute | ||||||||||||
3831 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3832 | } | ||||||||||||
3833 | } else { | ||||||||||||
3834 | // Unknown attribute | ||||||||||||
3835 | cfs->skip_u1(attribute_length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3836 | } | ||||||||||||
3837 | } | ||||||||||||
3838 | _class_annotations = assemble_annotations(runtime_visible_annotations, | ||||||||||||
3839 | runtime_visible_annotations_length, | ||||||||||||
3840 | runtime_invisible_annotations, | ||||||||||||
3841 | runtime_invisible_annotations_length, | ||||||||||||
3842 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3843 | _class_type_annotations = assemble_annotations(runtime_visible_type_annotations, | ||||||||||||
3844 | runtime_visible_type_annotations_length, | ||||||||||||
3845 | runtime_invisible_type_annotations, | ||||||||||||
3846 | runtime_invisible_type_annotations_length, | ||||||||||||
3847 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3848 | |||||||||||||
3849 | if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) { | ||||||||||||
3850 | const u2 num_of_classes = parse_classfile_inner_classes_attribute( | ||||||||||||
3851 | cfs, | ||||||||||||
3852 | cp, | ||||||||||||
3853 | inner_classes_attribute_start, | ||||||||||||
3854 | parsed_innerclasses_attribute, | ||||||||||||
3855 | enclosing_method_class_index, | ||||||||||||
3856 | enclosing_method_method_index, | ||||||||||||
3857 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3858 | if (parsed_innerclasses_attribute && _need_verify && _major_version >= JAVA_1_5_VERSION49) { | ||||||||||||
3859 | guarantee_property( | ||||||||||||
3860 | inner_classes_attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes, | ||||||||||||
3861 | "Wrong InnerClasses attribute length in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3862 | } | ||||||||||||
3863 | } | ||||||||||||
3864 | |||||||||||||
3865 | if (parsed_nest_members_attribute) { | ||||||||||||
3866 | const u2 num_of_classes = parse_classfile_nest_members_attribute( | ||||||||||||
3867 | cfs, | ||||||||||||
3868 | nest_members_attribute_start, | ||||||||||||
3869 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3870 | if (_need_verify) { | ||||||||||||
3871 | guarantee_property( | ||||||||||||
3872 | nest_members_attribute_length == sizeof(num_of_classes) + sizeof(u2) * num_of_classes, | ||||||||||||
3873 | "Wrong NestMembers attribute length in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3874 | } | ||||||||||||
3875 | } | ||||||||||||
3876 | |||||||||||||
3877 | if (parsed_record_attribute) { | ||||||||||||
3878 | const unsigned int calculated_attr_length = parse_classfile_record_attribute( | ||||||||||||
3879 | cfs, | ||||||||||||
3880 | cp, | ||||||||||||
3881 | record_attribute_start, | ||||||||||||
3882 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3883 | if (_need_verify) { | ||||||||||||
3884 | guarantee_property(record_attribute_length == calculated_attr_length, | ||||||||||||
3885 | "Record attribute has wrong length in class file %s", | ||||||||||||
3886 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3887 | } | ||||||||||||
3888 | } | ||||||||||||
3889 | |||||||||||||
3890 | if (parsed_permitted_subclasses_attribute) { | ||||||||||||
3891 | const u2 num_subclasses = parse_classfile_permitted_subclasses_attribute( | ||||||||||||
3892 | cfs, | ||||||||||||
3893 | permitted_subclasses_attribute_start, | ||||||||||||
3894 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3895 | if (_need_verify) { | ||||||||||||
3896 | guarantee_property( | ||||||||||||
3897 | permitted_subclasses_attribute_length == sizeof(num_subclasses) + sizeof(u2) * num_subclasses, | ||||||||||||
3898 | "Wrong PermittedSubclasses attribute length in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3899 | } | ||||||||||||
3900 | } | ||||||||||||
3901 | |||||||||||||
3902 | if (_max_bootstrap_specifier_index >= 0) { | ||||||||||||
3903 | guarantee_property(parsed_bootstrap_methods_attribute, | ||||||||||||
3904 | "Missing BootstrapMethods attribute in class file %s", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3905 | } | ||||||||||||
3906 | } | ||||||||||||
3907 | |||||||||||||
3908 | void ClassFileParser::apply_parsed_class_attributes(InstanceKlass* k) { | ||||||||||||
3909 | assert(k != NULL, "invariant")do { if (!(k != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3909, "assert(" "k != __null" ") failed", "invariant"); ::breakpoint (); } } while (0); | ||||||||||||
3910 | |||||||||||||
3911 | if (_synthetic_flag) | ||||||||||||
3912 | k->set_is_synthetic(); | ||||||||||||
3913 | if (_sourcefile_index != 0) { | ||||||||||||
3914 | k->set_source_file_name_index(_sourcefile_index); | ||||||||||||
3915 | } | ||||||||||||
3916 | if (_generic_signature_index != 0) { | ||||||||||||
3917 | k->set_generic_signature_index(_generic_signature_index); | ||||||||||||
3918 | } | ||||||||||||
3919 | if (_sde_buffer != NULL__null) { | ||||||||||||
3920 | k->set_source_debug_extension(_sde_buffer, _sde_length); | ||||||||||||
3921 | } | ||||||||||||
3922 | } | ||||||||||||
3923 | |||||||||||||
3924 | // Create the Annotations object that will | ||||||||||||
3925 | // hold the annotations array for the Klass. | ||||||||||||
3926 | void ClassFileParser::create_combined_annotations(TRAPSJavaThread* __the_thread__) { | ||||||||||||
3927 | if (_class_annotations == NULL__null && | ||||||||||||
3928 | _class_type_annotations == NULL__null && | ||||||||||||
3929 | _fields_annotations == NULL__null && | ||||||||||||
3930 | _fields_type_annotations == NULL__null) { | ||||||||||||
3931 | // Don't create the Annotations object unnecessarily. | ||||||||||||
3932 | return; | ||||||||||||
3933 | } | ||||||||||||
3934 | |||||||||||||
3935 | Annotations* const annotations = Annotations::allocate(_loader_data, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
3936 | annotations->set_class_annotations(_class_annotations); | ||||||||||||
3937 | annotations->set_class_type_annotations(_class_type_annotations); | ||||||||||||
3938 | annotations->set_fields_annotations(_fields_annotations); | ||||||||||||
3939 | annotations->set_fields_type_annotations(_fields_type_annotations); | ||||||||||||
3940 | |||||||||||||
3941 | // This is the Annotations object that will be | ||||||||||||
3942 | // assigned to InstanceKlass being constructed. | ||||||||||||
3943 | _combined_annotations = annotations; | ||||||||||||
3944 | |||||||||||||
3945 | // The annotations arrays below has been transfered the | ||||||||||||
3946 | // _combined_annotations so these fields can now be cleared. | ||||||||||||
3947 | _class_annotations = NULL__null; | ||||||||||||
3948 | _class_type_annotations = NULL__null; | ||||||||||||
3949 | _fields_annotations = NULL__null; | ||||||||||||
3950 | _fields_type_annotations = NULL__null; | ||||||||||||
3951 | } | ||||||||||||
3952 | |||||||||||||
3953 | // Transfer ownership of metadata allocated to the InstanceKlass. | ||||||||||||
3954 | void ClassFileParser::apply_parsed_class_metadata( | ||||||||||||
3955 | InstanceKlass* this_klass, | ||||||||||||
3956 | int java_fields_count) { | ||||||||||||
3957 | assert(this_klass != NULL, "invariant")do { if (!(this_klass != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 3957, "assert(" "this_klass != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
3958 | |||||||||||||
3959 | _cp->set_pool_holder(this_klass); | ||||||||||||
3960 | this_klass->set_constants(_cp); | ||||||||||||
3961 | this_klass->set_fields(_fields, java_fields_count); | ||||||||||||
3962 | this_klass->set_methods(_methods); | ||||||||||||
3963 | this_klass->set_inner_classes(_inner_classes); | ||||||||||||
3964 | this_klass->set_nest_members(_nest_members); | ||||||||||||
3965 | this_klass->set_nest_host_index(_nest_host); | ||||||||||||
3966 | this_klass->set_annotations(_combined_annotations); | ||||||||||||
3967 | this_klass->set_permitted_subclasses(_permitted_subclasses); | ||||||||||||
3968 | this_klass->set_record_components(_record_components); | ||||||||||||
3969 | // Delay the setting of _local_interfaces and _transitive_interfaces until after | ||||||||||||
3970 | // initialize_supers() in fill_instance_klass(). It is because the _local_interfaces could | ||||||||||||
3971 | // be shared with _transitive_interfaces and _transitive_interfaces may be shared with | ||||||||||||
3972 | // its _super. If an OOM occurs while loading the current klass, its _super field | ||||||||||||
3973 | // may not have been set. When GC tries to free the klass, the _transitive_interfaces | ||||||||||||
3974 | // may be deallocated mistakenly in InstanceKlass::deallocate_interfaces(). Subsequent | ||||||||||||
3975 | // dereferences to the deallocated _transitive_interfaces will result in a crash. | ||||||||||||
3976 | |||||||||||||
3977 | // Clear out these fields so they don't get deallocated by the destructor | ||||||||||||
3978 | clear_class_metadata(); | ||||||||||||
3979 | } | ||||||||||||
3980 | |||||||||||||
3981 | AnnotationArray* ClassFileParser::assemble_annotations(const u1* const runtime_visible_annotations, | ||||||||||||
3982 | int runtime_visible_annotations_length, | ||||||||||||
3983 | const u1* const runtime_invisible_annotations, | ||||||||||||
3984 | int runtime_invisible_annotations_length, | ||||||||||||
3985 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
3986 | AnnotationArray* annotations = NULL__null; | ||||||||||||
3987 | if (runtime_visible_annotations != NULL__null || | ||||||||||||
3988 | runtime_invisible_annotations != NULL__null) { | ||||||||||||
3989 | annotations = MetadataFactory::new_array<u1>(_loader_data, | ||||||||||||
3990 | runtime_visible_annotations_length + | ||||||||||||
3991 | runtime_invisible_annotations_length, | ||||||||||||
3992 | CHECK_(annotations)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return annotations; (void)(0); | ||||||||||||
3993 | if (runtime_visible_annotations != NULL__null) { | ||||||||||||
3994 | for (int i = 0; i < runtime_visible_annotations_length; i++) { | ||||||||||||
3995 | annotations->at_put(i, runtime_visible_annotations[i]); | ||||||||||||
3996 | } | ||||||||||||
3997 | } | ||||||||||||
3998 | if (runtime_invisible_annotations != NULL__null) { | ||||||||||||
3999 | for (int i = 0; i < runtime_invisible_annotations_length; i++) { | ||||||||||||
4000 | int append = runtime_visible_annotations_length+i; | ||||||||||||
4001 | annotations->at_put(append, runtime_invisible_annotations[i]); | ||||||||||||
4002 | } | ||||||||||||
4003 | } | ||||||||||||
4004 | } | ||||||||||||
4005 | return annotations; | ||||||||||||
4006 | } | ||||||||||||
4007 | |||||||||||||
4008 | const InstanceKlass* ClassFileParser::parse_super_class(ConstantPool* const cp, | ||||||||||||
4009 | const int super_class_index, | ||||||||||||
4010 | const bool need_verify, | ||||||||||||
4011 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
4012 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4012, "assert(" "cp != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
4013 | const InstanceKlass* super_klass = NULL__null; | ||||||||||||
4014 | |||||||||||||
4015 | if (super_class_index == 0) { | ||||||||||||
4016 | check_property(_class_name == vmSymbols::java_lang_Object(), | ||||||||||||
4017 | "Invalid superclass index %u in class file %s", | ||||||||||||
4018 | super_class_index, | ||||||||||||
4019 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
4020 | } else { | ||||||||||||
4021 | check_property(valid_klass_reference_at(super_class_index), | ||||||||||||
4022 | "Invalid superclass index %u in class file %s", | ||||||||||||
4023 | super_class_index, | ||||||||||||
4024 | CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
4025 | // The class name should be legal because it is checked when parsing constant pool. | ||||||||||||
4026 | // However, make sure it is not an array type. | ||||||||||||
4027 | bool is_array = false; | ||||||||||||
4028 | if (cp->tag_at(super_class_index).is_klass()) { | ||||||||||||
4029 | super_klass = InstanceKlass::cast(cp->resolved_klass_at(super_class_index)); | ||||||||||||
4030 | if (need_verify) | ||||||||||||
4031 | is_array = super_klass->is_array_klass(); | ||||||||||||
4032 | } else if (need_verify) { | ||||||||||||
4033 | is_array = (cp->klass_name_at(super_class_index)->char_at(0) == JVM_SIGNATURE_ARRAY); | ||||||||||||
4034 | } | ||||||||||||
4035 | if (need_verify) { | ||||||||||||
4036 | guarantee_property(!is_array, | ||||||||||||
4037 | "Bad superclass name in class file %s", CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
4038 | } | ||||||||||||
4039 | } | ||||||||||||
4040 | return super_klass; | ||||||||||||
4041 | } | ||||||||||||
4042 | |||||||||||||
4043 | OopMapBlocksBuilder::OopMapBlocksBuilder(unsigned int max_blocks) { | ||||||||||||
4044 | _max_nonstatic_oop_maps = max_blocks; | ||||||||||||
4045 | _nonstatic_oop_map_count = 0; | ||||||||||||
4046 | if (max_blocks == 0) { | ||||||||||||
4047 | _nonstatic_oop_maps = NULL__null; | ||||||||||||
4048 | } else { | ||||||||||||
4049 | _nonstatic_oop_maps = | ||||||||||||
4050 | NEW_RESOURCE_ARRAY(OopMapBlock, _max_nonstatic_oop_maps)(OopMapBlock*) resource_allocate_bytes((_max_nonstatic_oop_maps ) * sizeof(OopMapBlock)); | ||||||||||||
4051 | memset(_nonstatic_oop_maps, 0, sizeof(OopMapBlock) * max_blocks); | ||||||||||||
4052 | } | ||||||||||||
4053 | } | ||||||||||||
4054 | |||||||||||||
4055 | OopMapBlock* OopMapBlocksBuilder::last_oop_map() const { | ||||||||||||
4056 | assert(_nonstatic_oop_map_count > 0, "Has no oop maps")do { if (!(_nonstatic_oop_map_count > 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4056, "assert(" "_nonstatic_oop_map_count > 0" ") failed" , "Has no oop maps"); ::breakpoint(); } } while (0); | ||||||||||||
4057 | return _nonstatic_oop_maps + (_nonstatic_oop_map_count - 1); | ||||||||||||
4058 | } | ||||||||||||
4059 | |||||||||||||
4060 | // addition of super oop maps | ||||||||||||
4061 | void OopMapBlocksBuilder::initialize_inherited_blocks(OopMapBlock* blocks, unsigned int nof_blocks) { | ||||||||||||
4062 | assert(nof_blocks && _nonstatic_oop_map_count == 0 &&do { if (!(nof_blocks && _nonstatic_oop_map_count == 0 && nof_blocks <= _max_nonstatic_oop_maps)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4063, "assert(" "nof_blocks && _nonstatic_oop_map_count == 0 && nof_blocks <= _max_nonstatic_oop_maps" ") failed", "invariant"); ::breakpoint(); } } while (0) | ||||||||||||
4063 | nof_blocks <= _max_nonstatic_oop_maps, "invariant")do { if (!(nof_blocks && _nonstatic_oop_map_count == 0 && nof_blocks <= _max_nonstatic_oop_maps)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4063, "assert(" "nof_blocks && _nonstatic_oop_map_count == 0 && nof_blocks <= _max_nonstatic_oop_maps" ") failed", "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
4064 | |||||||||||||
4065 | memcpy(_nonstatic_oop_maps, blocks, sizeof(OopMapBlock) * nof_blocks); | ||||||||||||
4066 | _nonstatic_oop_map_count += nof_blocks; | ||||||||||||
4067 | } | ||||||||||||
4068 | |||||||||||||
4069 | // collection of oops | ||||||||||||
4070 | void OopMapBlocksBuilder::add(int offset, int count) { | ||||||||||||
4071 | if (_nonstatic_oop_map_count == 0) { | ||||||||||||
4072 | _nonstatic_oop_map_count++; | ||||||||||||
4073 | } | ||||||||||||
4074 | OopMapBlock* nonstatic_oop_map = last_oop_map(); | ||||||||||||
4075 | if (nonstatic_oop_map->count() == 0) { // Unused map, set it up | ||||||||||||
4076 | nonstatic_oop_map->set_offset(offset); | ||||||||||||
4077 | nonstatic_oop_map->set_count(count); | ||||||||||||
4078 | } else if (nonstatic_oop_map->is_contiguous(offset)) { // contiguous, add | ||||||||||||
4079 | nonstatic_oop_map->increment_count(count); | ||||||||||||
4080 | } else { // Need a new one... | ||||||||||||
4081 | _nonstatic_oop_map_count++; | ||||||||||||
4082 | assert(_nonstatic_oop_map_count <= _max_nonstatic_oop_maps, "range check")do { if (!(_nonstatic_oop_map_count <= _max_nonstatic_oop_maps )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4082, "assert(" "_nonstatic_oop_map_count <= _max_nonstatic_oop_maps" ") failed", "range check"); ::breakpoint(); } } while (0); | ||||||||||||
4083 | nonstatic_oop_map = last_oop_map(); | ||||||||||||
4084 | nonstatic_oop_map->set_offset(offset); | ||||||||||||
4085 | nonstatic_oop_map->set_count(count); | ||||||||||||
4086 | } | ||||||||||||
4087 | } | ||||||||||||
4088 | |||||||||||||
4089 | // general purpose copy, e.g. into allocated instanceKlass | ||||||||||||
4090 | void OopMapBlocksBuilder::copy(OopMapBlock* dst) { | ||||||||||||
4091 | if (_nonstatic_oop_map_count != 0) { | ||||||||||||
4092 | memcpy(dst, _nonstatic_oop_maps, sizeof(OopMapBlock) * _nonstatic_oop_map_count); | ||||||||||||
4093 | } | ||||||||||||
4094 | } | ||||||||||||
4095 | |||||||||||||
4096 | // Sort and compact adjacent blocks | ||||||||||||
4097 | void OopMapBlocksBuilder::compact() { | ||||||||||||
4098 | if (_nonstatic_oop_map_count <= 1) { | ||||||||||||
4099 | return; | ||||||||||||
4100 | } | ||||||||||||
4101 | /* | ||||||||||||
4102 | * Since field layout sneeks in oops before values, we will be able to condense | ||||||||||||
4103 | * blocks. There is potential to compact between super, own refs and values | ||||||||||||
4104 | * containing refs. | ||||||||||||
4105 | * | ||||||||||||
4106 | * Currently compaction is slightly limited due to values being 8 byte aligned. | ||||||||||||
4107 | * This may well change: FixMe if it doesn't, the code below is fairly general purpose | ||||||||||||
4108 | * and maybe it doesn't need to be. | ||||||||||||
4109 | */ | ||||||||||||
4110 | qsort(_nonstatic_oop_maps, _nonstatic_oop_map_count, sizeof(OopMapBlock), | ||||||||||||
4111 | (_sort_Fn)OopMapBlock::compare_offset); | ||||||||||||
4112 | if (_nonstatic_oop_map_count < 2) { | ||||||||||||
4113 | return; | ||||||||||||
4114 | } | ||||||||||||
4115 | |||||||||||||
4116 | // Make a temp copy, and iterate through and copy back into the original | ||||||||||||
4117 | ResourceMark rm; | ||||||||||||
4118 | OopMapBlock* oop_maps_copy = | ||||||||||||
4119 | NEW_RESOURCE_ARRAY(OopMapBlock, _nonstatic_oop_map_count)(OopMapBlock*) resource_allocate_bytes((_nonstatic_oop_map_count ) * sizeof(OopMapBlock)); | ||||||||||||
4120 | OopMapBlock* oop_maps_copy_end = oop_maps_copy + _nonstatic_oop_map_count; | ||||||||||||
4121 | copy(oop_maps_copy); | ||||||||||||
4122 | OopMapBlock* nonstatic_oop_map = _nonstatic_oop_maps; | ||||||||||||
4123 | unsigned int new_count = 1; | ||||||||||||
4124 | oop_maps_copy++; | ||||||||||||
4125 | while(oop_maps_copy < oop_maps_copy_end) { | ||||||||||||
4126 | assert(nonstatic_oop_map->offset() < oop_maps_copy->offset(), "invariant")do { if (!(nonstatic_oop_map->offset() < oop_maps_copy-> offset())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4126, "assert(" "nonstatic_oop_map->offset() < oop_maps_copy->offset()" ") failed", "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
4127 | if (nonstatic_oop_map->is_contiguous(oop_maps_copy->offset())) { | ||||||||||||
4128 | nonstatic_oop_map->increment_count(oop_maps_copy->count()); | ||||||||||||
4129 | } else { | ||||||||||||
4130 | nonstatic_oop_map++; | ||||||||||||
4131 | new_count++; | ||||||||||||
4132 | nonstatic_oop_map->set_offset(oop_maps_copy->offset()); | ||||||||||||
4133 | nonstatic_oop_map->set_count(oop_maps_copy->count()); | ||||||||||||
4134 | } | ||||||||||||
4135 | oop_maps_copy++; | ||||||||||||
4136 | } | ||||||||||||
4137 | assert(new_count <= _nonstatic_oop_map_count, "end up with more maps after compact() ?")do { if (!(new_count <= _nonstatic_oop_map_count)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4137, "assert(" "new_count <= _nonstatic_oop_map_count" ") failed" , "end up with more maps after compact() ?"); ::breakpoint(); } } while (0); | ||||||||||||
4138 | _nonstatic_oop_map_count = new_count; | ||||||||||||
4139 | } | ||||||||||||
4140 | |||||||||||||
4141 | void OopMapBlocksBuilder::print_on(outputStream* st) const { | ||||||||||||
4142 | st->print_cr(" OopMapBlocks: %3d /%3d", _nonstatic_oop_map_count, _max_nonstatic_oop_maps); | ||||||||||||
4143 | if (_nonstatic_oop_map_count > 0) { | ||||||||||||
4144 | OopMapBlock* map = _nonstatic_oop_maps; | ||||||||||||
4145 | OopMapBlock* last_map = last_oop_map(); | ||||||||||||
4146 | assert(map <= last_map, "Last less than first")do { if (!(map <= last_map)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4146, "assert(" "map <= last_map" ") failed", "Last less than first" ); ::breakpoint(); } } while (0); | ||||||||||||
4147 | while (map <= last_map) { | ||||||||||||
4148 | st->print_cr(" Offset: %3d -%3d Count: %3d", map->offset(), | ||||||||||||
4149 | map->offset() + map->offset_span() - heapOopSize, map->count()); | ||||||||||||
4150 | map++; | ||||||||||||
4151 | } | ||||||||||||
4152 | } | ||||||||||||
4153 | } | ||||||||||||
4154 | |||||||||||||
4155 | void OopMapBlocksBuilder::print_value_on(outputStream* st) const { | ||||||||||||
4156 | print_on(st); | ||||||||||||
4157 | } | ||||||||||||
4158 | |||||||||||||
4159 | void ClassFileParser::set_precomputed_flags(InstanceKlass* ik) { | ||||||||||||
4160 | assert(ik != NULL, "invariant")do { if (!(ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4160, "assert(" "ik != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
4161 | |||||||||||||
4162 | const Klass* const super = ik->super(); | ||||||||||||
4163 | |||||||||||||
4164 | // Check if this klass has an empty finalize method (i.e. one with return bytecode only), | ||||||||||||
4165 | // in which case we don't have to register objects as finalizable | ||||||||||||
4166 | if (!_has_empty_finalizer) { | ||||||||||||
4167 | if (_has_finalizer || | ||||||||||||
4168 | (super != NULL__null && super->has_finalizer())) { | ||||||||||||
4169 | ik->set_has_finalizer(); | ||||||||||||
4170 | } | ||||||||||||
4171 | } | ||||||||||||
4172 | |||||||||||||
4173 | #ifdef ASSERT1 | ||||||||||||
4174 | bool f = false; | ||||||||||||
4175 | const Method* const m = ik->lookup_method(vmSymbols::finalize_method_name(), | ||||||||||||
4176 | vmSymbols::void_method_signature()); | ||||||||||||
4177 | if (InstanceKlass::is_finalization_enabled() && | ||||||||||||
4178 | (m != NULL__null) && !m->is_empty_method()) { | ||||||||||||
4179 | f = true; | ||||||||||||
4180 | } | ||||||||||||
4181 | |||||||||||||
4182 | // Spec doesn't prevent agent from redefinition of empty finalizer. | ||||||||||||
4183 | // Despite the fact that it's generally bad idea and redefined finalizer | ||||||||||||
4184 | // will not work as expected we shouldn't abort vm in this case | ||||||||||||
4185 | if (!ik->has_redefined_this_or_super()) { | ||||||||||||
4186 | assert(ik->has_finalizer() == f, "inconsistent has_finalizer")do { if (!(ik->has_finalizer() == f)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4186, "assert(" "ik->has_finalizer() == f" ") failed", "inconsistent has_finalizer" ); ::breakpoint(); } } while (0); | ||||||||||||
4187 | } | ||||||||||||
4188 | #endif | ||||||||||||
4189 | |||||||||||||
4190 | // Check if this klass supports the java.lang.Cloneable interface | ||||||||||||
4191 | if (vmClasses::Cloneable_klass_loaded()) { | ||||||||||||
4192 | if (ik->is_subtype_of(vmClasses::Cloneable_klass())) { | ||||||||||||
4193 | ik->set_is_cloneable(); | ||||||||||||
4194 | } | ||||||||||||
4195 | } | ||||||||||||
4196 | |||||||||||||
4197 | // Check if this klass has a vanilla default constructor | ||||||||||||
4198 | if (super == NULL__null) { | ||||||||||||
4199 | // java.lang.Object has empty default constructor | ||||||||||||
4200 | ik->set_has_vanilla_constructor(); | ||||||||||||
4201 | } else { | ||||||||||||
4202 | if (super->has_vanilla_constructor() && | ||||||||||||
4203 | _has_vanilla_constructor) { | ||||||||||||
4204 | ik->set_has_vanilla_constructor(); | ||||||||||||
4205 | } | ||||||||||||
4206 | #ifdef ASSERT1 | ||||||||||||
4207 | bool v = false; | ||||||||||||
4208 | if (super->has_vanilla_constructor()) { | ||||||||||||
4209 | const Method* const constructor = | ||||||||||||
4210 | ik->find_method(vmSymbols::object_initializer_name(), | ||||||||||||
4211 | vmSymbols::void_method_signature()); | ||||||||||||
4212 | if (constructor != NULL__null && constructor->is_vanilla_constructor()) { | ||||||||||||
4213 | v = true; | ||||||||||||
4214 | } | ||||||||||||
4215 | } | ||||||||||||
4216 | assert(v == ik->has_vanilla_constructor(), "inconsistent has_vanilla_constructor")do { if (!(v == ik->has_vanilla_constructor())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4216, "assert(" "v == ik->has_vanilla_constructor()" ") failed" , "inconsistent has_vanilla_constructor"); ::breakpoint(); } } while (0); | ||||||||||||
4217 | #endif | ||||||||||||
4218 | } | ||||||||||||
4219 | |||||||||||||
4220 | // If it cannot be fast-path allocated, set a bit in the layout helper. | ||||||||||||
4221 | // See documentation of InstanceKlass::can_be_fastpath_allocated(). | ||||||||||||
4222 | assert(ik->size_helper() > 0, "layout_helper is initialized")do { if (!(ik->size_helper() > 0)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4222, "assert(" "ik->size_helper() > 0" ") failed", "layout_helper is initialized" ); ::breakpoint(); } } while (0); | ||||||||||||
4223 | if ((!RegisterFinalizersAtInit && ik->has_finalizer()) | ||||||||||||
4224 | || ik->is_abstract() || ik->is_interface() | ||||||||||||
4225 | || (ik->name() == vmSymbols::java_lang_Class() && ik->class_loader() == NULL__null) | ||||||||||||
4226 | || ik->size_helper() >= FastAllocateSizeLimit) { | ||||||||||||
4227 | // Forbid fast-path allocation. | ||||||||||||
4228 | const jint lh = Klass::instance_layout_helper(ik->size_helper(), true); | ||||||||||||
4229 | ik->set_layout_helper(lh); | ||||||||||||
4230 | } | ||||||||||||
4231 | } | ||||||||||||
4232 | |||||||||||||
4233 | // utility methods for appending an array with check for duplicates | ||||||||||||
4234 | |||||||||||||
4235 | static void append_interfaces(GrowableArray<InstanceKlass*>* result, | ||||||||||||
4236 | const Array<InstanceKlass*>* const ifs) { | ||||||||||||
4237 | // iterate over new interfaces | ||||||||||||
4238 | for (int i = 0; i < ifs->length(); i++) { | ||||||||||||
4239 | InstanceKlass* const e = ifs->at(i); | ||||||||||||
4240 | assert(e->is_klass() && e->is_interface(), "just checking")do { if (!(e->is_klass() && e->is_interface())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4240, "assert(" "e->is_klass() && e->is_interface()" ") failed", "just checking"); ::breakpoint(); } } while (0); | ||||||||||||
4241 | // add new interface | ||||||||||||
4242 | result->append_if_missing(e); | ||||||||||||
4243 | } | ||||||||||||
4244 | } | ||||||||||||
4245 | |||||||||||||
4246 | static Array<InstanceKlass*>* compute_transitive_interfaces(const InstanceKlass* super, | ||||||||||||
4247 | Array<InstanceKlass*>* local_ifs, | ||||||||||||
4248 | ClassLoaderData* loader_data, | ||||||||||||
4249 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
4250 | assert(local_ifs != NULL, "invariant")do { if (!(local_ifs != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4250, "assert(" "local_ifs != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
4251 | assert(loader_data != NULL, "invariant")do { if (!(loader_data != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4251, "assert(" "loader_data != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
4252 | |||||||||||||
4253 | // Compute maximum size for transitive interfaces | ||||||||||||
4254 | int max_transitive_size = 0; | ||||||||||||
4255 | int super_size = 0; | ||||||||||||
4256 | // Add superclass transitive interfaces size | ||||||||||||
4257 | if (super != NULL__null) { | ||||||||||||
4258 | super_size = super->transitive_interfaces()->length(); | ||||||||||||
4259 | max_transitive_size += super_size; | ||||||||||||
4260 | } | ||||||||||||
4261 | // Add local interfaces' super interfaces | ||||||||||||
4262 | const int local_size = local_ifs->length(); | ||||||||||||
4263 | for (int i = 0; i < local_size; i++) { | ||||||||||||
4264 | InstanceKlass* const l = local_ifs->at(i); | ||||||||||||
4265 | max_transitive_size += l->transitive_interfaces()->length(); | ||||||||||||
4266 | } | ||||||||||||
4267 | // Finally add local interfaces | ||||||||||||
4268 | max_transitive_size += local_size; | ||||||||||||
4269 | // Construct array | ||||||||||||
4270 | if (max_transitive_size == 0) { | ||||||||||||
4271 | // no interfaces, use canonicalized array | ||||||||||||
4272 | return Universe::the_empty_instance_klass_array(); | ||||||||||||
4273 | } else if (max_transitive_size == super_size) { | ||||||||||||
4274 | // no new local interfaces added, share superklass' transitive interface array | ||||||||||||
4275 | return super->transitive_interfaces(); | ||||||||||||
4276 | } else if (max_transitive_size == local_size) { | ||||||||||||
4277 | // only local interfaces added, share local interface array | ||||||||||||
4278 | return local_ifs; | ||||||||||||
4279 | } else { | ||||||||||||
4280 | ResourceMark rm; | ||||||||||||
4281 | GrowableArray<InstanceKlass*>* const result = new GrowableArray<InstanceKlass*>(max_transitive_size); | ||||||||||||
4282 | |||||||||||||
4283 | // Copy down from superclass | ||||||||||||
4284 | if (super != NULL__null) { | ||||||||||||
4285 | append_interfaces(result, super->transitive_interfaces()); | ||||||||||||
4286 | } | ||||||||||||
4287 | |||||||||||||
4288 | // Copy down from local interfaces' superinterfaces | ||||||||||||
4289 | for (int i = 0; i < local_size; i++) { | ||||||||||||
4290 | InstanceKlass* const l = local_ifs->at(i); | ||||||||||||
4291 | append_interfaces(result, l->transitive_interfaces()); | ||||||||||||
4292 | } | ||||||||||||
4293 | // Finally add local interfaces | ||||||||||||
4294 | append_interfaces(result, local_ifs); | ||||||||||||
4295 | |||||||||||||
4296 | // length will be less than the max_transitive_size if duplicates were removed | ||||||||||||
4297 | const int length = result->length(); | ||||||||||||
4298 | assert(length <= max_transitive_size, "just checking")do { if (!(length <= max_transitive_size)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4298, "assert(" "length <= max_transitive_size" ") failed" , "just checking"); ::breakpoint(); } } while (0); | ||||||||||||
4299 | Array<InstanceKlass*>* const new_result = | ||||||||||||
4300 | MetadataFactory::new_array<InstanceKlass*>(loader_data, length, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
4301 | for (int i = 0; i < length; i++) { | ||||||||||||
4302 | InstanceKlass* const e = result->at(i); | ||||||||||||
4303 | assert(e != NULL, "just checking")do { if (!(e != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4303, "assert(" "e != __null" ") failed", "just checking"); ::breakpoint(); } } while (0); | ||||||||||||
4304 | new_result->at_put(i, e); | ||||||||||||
4305 | } | ||||||||||||
4306 | return new_result; | ||||||||||||
4307 | } | ||||||||||||
4308 | } | ||||||||||||
4309 | |||||||||||||
4310 | void ClassFileParser::check_super_class_access(const InstanceKlass* this_klass, TRAPSJavaThread* __the_thread__) { | ||||||||||||
4311 | assert(this_klass != NULL, "invariant")do { if (!(this_klass != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4311, "assert(" "this_klass != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
4312 | const Klass* const super = this_klass->super(); | ||||||||||||
4313 | |||||||||||||
4314 | if (super != NULL__null) { | ||||||||||||
4315 | const InstanceKlass* super_ik = InstanceKlass::cast(super); | ||||||||||||
4316 | |||||||||||||
4317 | if (super->is_final()) { | ||||||||||||
4318 | classfile_icce_error("class %s cannot inherit from final class %s", super_ik, THREAD__the_thread__); | ||||||||||||
4319 | return; | ||||||||||||
4320 | } | ||||||||||||
4321 | |||||||||||||
4322 | if (super_ik->is_sealed() && !super_ik->has_as_permitted_subclass(this_klass)) { | ||||||||||||
4323 | classfile_icce_error("class %s cannot inherit from sealed class %s", super_ik, THREAD__the_thread__); | ||||||||||||
4324 | return; | ||||||||||||
4325 | } | ||||||||||||
4326 | |||||||||||||
4327 | // If the loader is not the boot loader then throw an exception if its | ||||||||||||
4328 | // superclass is in package jdk.internal.reflect and its loader is not a | ||||||||||||
4329 | // special reflection class loader | ||||||||||||
4330 | if (!this_klass->class_loader_data()->is_the_null_class_loader_data()) { | ||||||||||||
4331 | PackageEntry* super_package = super->package(); | ||||||||||||
4332 | if (super_package != NULL__null && | ||||||||||||
4333 | super_package->name()->fast_compare(vmSymbols::jdk_internal_reflect()) == 0 && | ||||||||||||
4334 | !java_lang_ClassLoader::is_reflection_class_loader(this_klass->class_loader())) { | ||||||||||||
4335 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
4336 | Exceptions::fthrow( | ||||||||||||
4337 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4337, | ||||||||||||
4338 | vmSymbols::java_lang_IllegalAccessError(), | ||||||||||||
4339 | "class %s loaded by %s cannot access jdk/internal/reflect superclass %s", | ||||||||||||
4340 | this_klass->external_name(), | ||||||||||||
4341 | this_klass->class_loader_data()->loader_name_and_id(), | ||||||||||||
4342 | super->external_name()); | ||||||||||||
4343 | return; | ||||||||||||
4344 | } | ||||||||||||
4345 | } | ||||||||||||
4346 | |||||||||||||
4347 | Reflection::VerifyClassAccessResults vca_result = | ||||||||||||
4348 | Reflection::verify_class_access(this_klass, InstanceKlass::cast(super), false); | ||||||||||||
4349 | if (vca_result != Reflection::ACCESS_OK) { | ||||||||||||
4350 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
4351 | char* msg = Reflection::verify_class_access_msg(this_klass, | ||||||||||||
4352 | InstanceKlass::cast(super), | ||||||||||||
4353 | vca_result); | ||||||||||||
4354 | if (msg == NULL__null) { | ||||||||||||
4355 | bool same_module = (this_klass->module() == super->module()); | ||||||||||||
4356 | Exceptions::fthrow( | ||||||||||||
4357 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4357, | ||||||||||||
4358 | vmSymbols::java_lang_IllegalAccessError(), | ||||||||||||
4359 | "class %s cannot access its %ssuperclass %s (%s%s%s)", | ||||||||||||
4360 | this_klass->external_name(), | ||||||||||||
4361 | super->is_abstract() ? "abstract " : "", | ||||||||||||
4362 | super->external_name(), | ||||||||||||
4363 | (same_module) ? this_klass->joint_in_module_of_loader(super) : this_klass->class_in_module_of_loader(), | ||||||||||||
4364 | (same_module) ? "" : "; ", | ||||||||||||
4365 | (same_module) ? "" : super->class_in_module_of_loader()); | ||||||||||||
4366 | } else { | ||||||||||||
4367 | // Add additional message content. | ||||||||||||
4368 | Exceptions::fthrow( | ||||||||||||
4369 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4369, | ||||||||||||
4370 | vmSymbols::java_lang_IllegalAccessError(), | ||||||||||||
4371 | "superclass access check failed: %s", | ||||||||||||
4372 | msg); | ||||||||||||
4373 | } | ||||||||||||
4374 | } | ||||||||||||
4375 | } | ||||||||||||
4376 | } | ||||||||||||
4377 | |||||||||||||
4378 | |||||||||||||
4379 | void ClassFileParser::check_super_interface_access(const InstanceKlass* this_klass, TRAPSJavaThread* __the_thread__) { | ||||||||||||
4380 | assert(this_klass != NULL, "invariant")do { if (!(this_klass != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4380, "assert(" "this_klass != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
4381 | const Array<InstanceKlass*>* const local_interfaces = this_klass->local_interfaces(); | ||||||||||||
4382 | const int lng = local_interfaces->length(); | ||||||||||||
4383 | for (int i = lng - 1; i >= 0; i--) { | ||||||||||||
4384 | InstanceKlass* const k = local_interfaces->at(i); | ||||||||||||
4385 | assert (k != NULL && k->is_interface(), "invalid interface")do { if (!(k != __null && k->is_interface())) { (* g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4385, "assert(" "k != __null && k->is_interface()" ") failed", "invalid interface"); ::breakpoint(); } } while ( 0); | ||||||||||||
4386 | |||||||||||||
4387 | if (k->is_sealed() && !k->has_as_permitted_subclass(this_klass)) { | ||||||||||||
4388 | classfile_icce_error(this_klass->is_interface() ? | ||||||||||||
4389 | "class %s cannot extend sealed interface %s" : | ||||||||||||
4390 | "class %s cannot implement sealed interface %s", | ||||||||||||
4391 | k, THREAD__the_thread__); | ||||||||||||
4392 | return; | ||||||||||||
4393 | } | ||||||||||||
4394 | |||||||||||||
4395 | Reflection::VerifyClassAccessResults vca_result = | ||||||||||||
4396 | Reflection::verify_class_access(this_klass, k, false); | ||||||||||||
4397 | if (vca_result != Reflection::ACCESS_OK) { | ||||||||||||
4398 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
4399 | char* msg = Reflection::verify_class_access_msg(this_klass, | ||||||||||||
4400 | k, | ||||||||||||
4401 | vca_result); | ||||||||||||
4402 | if (msg == NULL__null) { | ||||||||||||
4403 | bool same_module = (this_klass->module() == k->module()); | ||||||||||||
4404 | Exceptions::fthrow( | ||||||||||||
4405 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4405, | ||||||||||||
4406 | vmSymbols::java_lang_IllegalAccessError(), | ||||||||||||
4407 | "class %s cannot access its superinterface %s (%s%s%s)", | ||||||||||||
4408 | this_klass->external_name(), | ||||||||||||
4409 | k->external_name(), | ||||||||||||
4410 | (same_module) ? this_klass->joint_in_module_of_loader(k) : this_klass->class_in_module_of_loader(), | ||||||||||||
4411 | (same_module) ? "" : "; ", | ||||||||||||
4412 | (same_module) ? "" : k->class_in_module_of_loader()); | ||||||||||||
4413 | } else { | ||||||||||||
4414 | // Add additional message content. | ||||||||||||
4415 | Exceptions::fthrow( | ||||||||||||
4416 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4416, | ||||||||||||
4417 | vmSymbols::java_lang_IllegalAccessError(), | ||||||||||||
4418 | "superinterface check failed: %s", | ||||||||||||
4419 | msg); | ||||||||||||
4420 | } | ||||||||||||
4421 | } | ||||||||||||
4422 | } | ||||||||||||
4423 | } | ||||||||||||
4424 | |||||||||||||
4425 | |||||||||||||
4426 | static void check_final_method_override(const InstanceKlass* this_klass, TRAPSJavaThread* __the_thread__) { | ||||||||||||
4427 | assert(this_klass != NULL, "invariant")do { if (!(this_klass != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4427, "assert(" "this_klass != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
4428 | const Array<Method*>* const methods = this_klass->methods(); | ||||||||||||
4429 | const int num_methods = methods->length(); | ||||||||||||
4430 | |||||||||||||
4431 | // go thru each method and check if it overrides a final method | ||||||||||||
4432 | for (int index = 0; index < num_methods; index++) { | ||||||||||||
4433 | const Method* const m = methods->at(index); | ||||||||||||
4434 | |||||||||||||
4435 | // skip private, static, and <init> methods | ||||||||||||
4436 | if ((!m->is_private() && !m->is_static()) && | ||||||||||||
4437 | (m->name() != vmSymbols::object_initializer_name())) { | ||||||||||||
4438 | |||||||||||||
4439 | const Symbol* const name = m->name(); | ||||||||||||
4440 | const Symbol* const signature = m->signature(); | ||||||||||||
4441 | const Klass* k = this_klass->super(); | ||||||||||||
4442 | const Method* super_m = NULL__null; | ||||||||||||
4443 | while (k != NULL__null) { | ||||||||||||
4444 | // skip supers that don't have final methods. | ||||||||||||
4445 | if (k->has_final_method()) { | ||||||||||||
4446 | // lookup a matching method in the super class hierarchy | ||||||||||||
4447 | super_m = InstanceKlass::cast(k)->lookup_method(name, signature); | ||||||||||||
4448 | if (super_m == NULL__null) { | ||||||||||||
4449 | break; // didn't find any match; get out | ||||||||||||
4450 | } | ||||||||||||
4451 | |||||||||||||
4452 | if (super_m->is_final() && !super_m->is_static() && | ||||||||||||
4453 | !super_m->access_flags().is_private()) { | ||||||||||||
4454 | // matching method in super is final, and not static or private | ||||||||||||
4455 | bool can_access = Reflection::verify_member_access(this_klass, | ||||||||||||
4456 | super_m->method_holder(), | ||||||||||||
4457 | super_m->method_holder(), | ||||||||||||
4458 | super_m->access_flags(), | ||||||||||||
4459 | false, false, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
4460 | if (can_access) { | ||||||||||||
4461 | // this class can access super final method and therefore override | ||||||||||||
4462 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
4463 | THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4468, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s overrides final method %s.%s%s", this_klass->external_name (), super_m->method_holder()->external_name(), name-> as_C_string(), signature->as_C_string())); return; } | ||||||||||||
4464 | err_msg("class %s overrides final method %s.%s%s",{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4468, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s overrides final method %s.%s%s", this_klass->external_name (), super_m->method_holder()->external_name(), name-> as_C_string(), signature->as_C_string())); return; } | ||||||||||||
4465 | this_klass->external_name(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4468, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s overrides final method %s.%s%s", this_klass->external_name (), super_m->method_holder()->external_name(), name-> as_C_string(), signature->as_C_string())); return; } | ||||||||||||
4466 | super_m->method_holder()->external_name(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4468, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s overrides final method %s.%s%s", this_klass->external_name (), super_m->method_holder()->external_name(), name-> as_C_string(), signature->as_C_string())); return; } | ||||||||||||
4467 | name->as_C_string(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4468, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s overrides final method %s.%s%s", this_klass->external_name (), super_m->method_holder()->external_name(), name-> as_C_string(), signature->as_C_string())); return; } | ||||||||||||
4468 | signature->as_C_string())){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4468, vmSymbols::java_lang_IncompatibleClassChangeError(), err_msg ("class %s overrides final method %s.%s%s", this_klass->external_name (), super_m->method_holder()->external_name(), name-> as_C_string(), signature->as_C_string())); return; }; | ||||||||||||
4469 | } | ||||||||||||
4470 | } | ||||||||||||
4471 | |||||||||||||
4472 | // continue to look from super_m's holder's super. | ||||||||||||
4473 | k = super_m->method_holder()->super(); | ||||||||||||
4474 | continue; | ||||||||||||
4475 | } | ||||||||||||
4476 | |||||||||||||
4477 | k = k->super(); | ||||||||||||
4478 | } | ||||||||||||
4479 | } | ||||||||||||
4480 | } | ||||||||||||
4481 | } | ||||||||||||
4482 | |||||||||||||
4483 | |||||||||||||
4484 | // assumes that this_klass is an interface | ||||||||||||
4485 | static void check_illegal_static_method(const InstanceKlass* this_klass, TRAPSJavaThread* __the_thread__) { | ||||||||||||
4486 | assert(this_klass != NULL, "invariant")do { if (!(this_klass != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4486, "assert(" "this_klass != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
4487 | assert(this_klass->is_interface(), "not an interface")do { if (!(this_klass->is_interface())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4487, "assert(" "this_klass->is_interface()" ") failed", "not an interface"); ::breakpoint(); } } while (0); | ||||||||||||
4488 | const Array<Method*>* methods = this_klass->methods(); | ||||||||||||
4489 | const int num_methods = methods->length(); | ||||||||||||
4490 | |||||||||||||
4491 | for (int index = 0; index < num_methods; index++) { | ||||||||||||
4492 | const Method* const m = methods->at(index); | ||||||||||||
4493 | // if m is static and not the init method, throw a verify error | ||||||||||||
4494 | if ((m->is_static()) && (m->name() != vmSymbols::class_initializer_name())) { | ||||||||||||
4495 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
4496 | Exceptions::fthrow( | ||||||||||||
4497 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4497, | ||||||||||||
4498 | vmSymbols::java_lang_VerifyError(), | ||||||||||||
4499 | "Illegal static method %s in interface %s", | ||||||||||||
4500 | m->name()->as_C_string(), | ||||||||||||
4501 | this_klass->external_name() | ||||||||||||
4502 | ); | ||||||||||||
4503 | return; | ||||||||||||
4504 | } | ||||||||||||
4505 | } | ||||||||||||
4506 | } | ||||||||||||
4507 | |||||||||||||
4508 | // utility methods for format checking | ||||||||||||
4509 | |||||||||||||
4510 | void ClassFileParser::verify_legal_class_modifiers(jint flags, TRAPSJavaThread* __the_thread__) const { | ||||||||||||
4511 | const bool is_module = (flags & JVM_ACC_MODULE) != 0; | ||||||||||||
4512 | assert(_major_version >= JAVA_9_VERSION || !is_module, "JVM_ACC_MODULE should not be set")do { if (!(_major_version >= 53 || !is_module)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4512, "assert(" "_major_version >= 53 || !is_module" ") failed" , "JVM_ACC_MODULE should not be set"); ::breakpoint(); } } while (0); | ||||||||||||
4513 | if (is_module) { | ||||||||||||
4514 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
4515 | Exceptions::fthrow( | ||||||||||||
4516 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4516, | ||||||||||||
4517 | vmSymbols::java_lang_NoClassDefFoundError(), | ||||||||||||
4518 | "%s is not a class because access_flag ACC_MODULE is set", | ||||||||||||
4519 | _class_name->as_C_string()); | ||||||||||||
4520 | return; | ||||||||||||
4521 | } | ||||||||||||
4522 | |||||||||||||
4523 | if (!_need_verify) { return; } | ||||||||||||
4524 | |||||||||||||
4525 | const bool is_interface = (flags & JVM_ACC_INTERFACE) != 0; | ||||||||||||
4526 | const bool is_abstract = (flags & JVM_ACC_ABSTRACT) != 0; | ||||||||||||
4527 | const bool is_final = (flags & JVM_ACC_FINAL) != 0; | ||||||||||||
4528 | const bool is_super = (flags & JVM_ACC_SUPER) != 0; | ||||||||||||
4529 | const bool is_enum = (flags & JVM_ACC_ENUM) != 0; | ||||||||||||
4530 | const bool is_annotation = (flags & JVM_ACC_ANNOTATION) != 0; | ||||||||||||
4531 | const bool major_gte_1_5 = _major_version >= JAVA_1_5_VERSION49; | ||||||||||||
4532 | |||||||||||||
4533 | if ((is_abstract && is_final) || | ||||||||||||
4534 | (is_interface && !is_abstract) || | ||||||||||||
4535 | (is_interface && major_gte_1_5 && (is_super || is_enum)) || | ||||||||||||
4536 | (!is_interface && major_gte_1_5 && is_annotation)) { | ||||||||||||
4537 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
4538 | Exceptions::fthrow( | ||||||||||||
4539 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4539, | ||||||||||||
4540 | vmSymbols::java_lang_ClassFormatError(), | ||||||||||||
4541 | "Illegal class modifiers in class %s: 0x%X", | ||||||||||||
4542 | _class_name->as_C_string(), flags | ||||||||||||
4543 | ); | ||||||||||||
4544 | return; | ||||||||||||
4545 | } | ||||||||||||
4546 | } | ||||||||||||
4547 | |||||||||||||
4548 | static bool has_illegal_visibility(jint flags) { | ||||||||||||
4549 | const bool is_public = (flags & JVM_ACC_PUBLIC) != 0; | ||||||||||||
4550 | const bool is_protected = (flags & JVM_ACC_PROTECTED) != 0; | ||||||||||||
4551 | const bool is_private = (flags & JVM_ACC_PRIVATE) != 0; | ||||||||||||
4552 | |||||||||||||
4553 | return ((is_public && is_protected) || | ||||||||||||
4554 | (is_public && is_private) || | ||||||||||||
4555 | (is_protected && is_private)); | ||||||||||||
4556 | } | ||||||||||||
4557 | |||||||||||||
4558 | // A legal major_version.minor_version must be one of the following: | ||||||||||||
4559 | // | ||||||||||||
4560 | // Major_version >= 45 and major_version < 56, any minor_version. | ||||||||||||
4561 | // Major_version >= 56 and major_version <= JVM_CLASSFILE_MAJOR_VERSION and minor_version = 0. | ||||||||||||
4562 | // Major_version = JVM_CLASSFILE_MAJOR_VERSION and minor_version = 65535 and --enable-preview is present. | ||||||||||||
4563 | // | ||||||||||||
4564 | void ClassFileParser::verify_class_version(u2 major, u2 minor, Symbol* class_name, TRAPSJavaThread* __the_thread__){ | ||||||||||||
4565 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
4566 | const u2 max_version = JVM_CLASSFILE_MAJOR_VERSION63; | ||||||||||||
4567 | if (major < JAVA_MIN_SUPPORTED_VERSION45) { | ||||||||||||
4568 | classfile_ucve_error("%s (class file version %u.%u) was compiled with an invalid major version", | ||||||||||||
4569 | class_name, major, minor, THREAD__the_thread__); | ||||||||||||
4570 | return; | ||||||||||||
4571 | } | ||||||||||||
4572 | |||||||||||||
4573 | if (major > max_version) { | ||||||||||||
4574 | Exceptions::fthrow( | ||||||||||||
4575 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4575, | ||||||||||||
4576 | vmSymbols::java_lang_UnsupportedClassVersionError(), | ||||||||||||
4577 | "%s has been compiled by a more recent version of the Java Runtime (class file version %u.%u), " | ||||||||||||
4578 | "this version of the Java Runtime only recognizes class file versions up to %u.0", | ||||||||||||
4579 | class_name->as_C_string(), major, minor, JVM_CLASSFILE_MAJOR_VERSION63); | ||||||||||||
4580 | return; | ||||||||||||
4581 | } | ||||||||||||
4582 | |||||||||||||
4583 | if (major < JAVA_12_VERSION56 || minor == 0) { | ||||||||||||
4584 | return; | ||||||||||||
4585 | } | ||||||||||||
4586 | |||||||||||||
4587 | if (minor == JAVA_PREVIEW_MINOR_VERSION65535) { | ||||||||||||
4588 | if (major != max_version) { | ||||||||||||
4589 | Exceptions::fthrow( | ||||||||||||
4590 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4590, | ||||||||||||
4591 | vmSymbols::java_lang_UnsupportedClassVersionError(), | ||||||||||||
4592 | "%s (class file version %u.%u) was compiled with preview features that are unsupported. " | ||||||||||||
4593 | "This version of the Java Runtime only recognizes preview features for class file version %u.%u", | ||||||||||||
4594 | class_name->as_C_string(), major, minor, JVM_CLASSFILE_MAJOR_VERSION63, JAVA_PREVIEW_MINOR_VERSION65535); | ||||||||||||
4595 | return; | ||||||||||||
4596 | } | ||||||||||||
4597 | |||||||||||||
4598 | if (!Arguments::enable_preview()) { | ||||||||||||
4599 | classfile_ucve_error("Preview features are not enabled for %s (class file version %u.%u). Try running with '--enable-preview'", | ||||||||||||
4600 | class_name, major, minor, THREAD__the_thread__); | ||||||||||||
4601 | return; | ||||||||||||
4602 | } | ||||||||||||
4603 | |||||||||||||
4604 | } else { // minor != JAVA_PREVIEW_MINOR_VERSION | ||||||||||||
4605 | classfile_ucve_error("%s (class file version %u.%u) was compiled with an invalid non-zero minor version", | ||||||||||||
4606 | class_name, major, minor, THREAD__the_thread__); | ||||||||||||
4607 | } | ||||||||||||
4608 | } | ||||||||||||
4609 | |||||||||||||
4610 | void ClassFileParser::verify_legal_field_modifiers(jint flags, | ||||||||||||
4611 | bool is_interface, | ||||||||||||
4612 | TRAPSJavaThread* __the_thread__) const { | ||||||||||||
4613 | if (!_need_verify) { return; } | ||||||||||||
4614 | |||||||||||||
4615 | const bool is_public = (flags & JVM_ACC_PUBLIC) != 0; | ||||||||||||
4616 | const bool is_protected = (flags & JVM_ACC_PROTECTED) != 0; | ||||||||||||
4617 | const bool is_private = (flags & JVM_ACC_PRIVATE) != 0; | ||||||||||||
4618 | const bool is_static = (flags & JVM_ACC_STATIC) != 0; | ||||||||||||
4619 | const bool is_final = (flags & JVM_ACC_FINAL) != 0; | ||||||||||||
4620 | const bool is_volatile = (flags & JVM_ACC_VOLATILE) != 0; | ||||||||||||
4621 | const bool is_transient = (flags & JVM_ACC_TRANSIENT) != 0; | ||||||||||||
4622 | const bool is_enum = (flags & JVM_ACC_ENUM) != 0; | ||||||||||||
4623 | const bool major_gte_1_5 = _major_version >= JAVA_1_5_VERSION49; | ||||||||||||
4624 | |||||||||||||
4625 | bool is_illegal = false; | ||||||||||||
4626 | |||||||||||||
4627 | if (is_interface) { | ||||||||||||
4628 | if (!is_public || !is_static || !is_final || is_private || | ||||||||||||
4629 | is_protected || is_volatile || is_transient || | ||||||||||||
4630 | (major_gte_1_5 && is_enum)) { | ||||||||||||
4631 | is_illegal = true; | ||||||||||||
4632 | } | ||||||||||||
4633 | } else { // not interface | ||||||||||||
4634 | if (has_illegal_visibility(flags) || (is_final && is_volatile)) { | ||||||||||||
4635 | is_illegal = true; | ||||||||||||
4636 | } | ||||||||||||
4637 | } | ||||||||||||
4638 | |||||||||||||
4639 | if (is_illegal) { | ||||||||||||
4640 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
4641 | Exceptions::fthrow( | ||||||||||||
4642 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4642, | ||||||||||||
4643 | vmSymbols::java_lang_ClassFormatError(), | ||||||||||||
4644 | "Illegal field modifiers in class %s: 0x%X", | ||||||||||||
4645 | _class_name->as_C_string(), flags); | ||||||||||||
4646 | return; | ||||||||||||
4647 | } | ||||||||||||
4648 | } | ||||||||||||
4649 | |||||||||||||
4650 | void ClassFileParser::verify_legal_method_modifiers(jint flags, | ||||||||||||
4651 | bool is_interface, | ||||||||||||
4652 | const Symbol* name, | ||||||||||||
4653 | TRAPSJavaThread* __the_thread__) const { | ||||||||||||
4654 | if (!_need_verify) { return; } | ||||||||||||
4655 | |||||||||||||
4656 | const bool is_public = (flags & JVM_ACC_PUBLIC) != 0; | ||||||||||||
4657 | const bool is_private = (flags & JVM_ACC_PRIVATE) != 0; | ||||||||||||
4658 | const bool is_static = (flags & JVM_ACC_STATIC) != 0; | ||||||||||||
4659 | const bool is_final = (flags & JVM_ACC_FINAL) != 0; | ||||||||||||
4660 | const bool is_native = (flags & JVM_ACC_NATIVE) != 0; | ||||||||||||
4661 | const bool is_abstract = (flags & JVM_ACC_ABSTRACT) != 0; | ||||||||||||
4662 | const bool is_bridge = (flags & JVM_ACC_BRIDGE) != 0; | ||||||||||||
4663 | const bool is_strict = (flags & JVM_ACC_STRICT) != 0; | ||||||||||||
4664 | const bool is_synchronized = (flags & JVM_ACC_SYNCHRONIZED) != 0; | ||||||||||||
4665 | const bool is_protected = (flags & JVM_ACC_PROTECTED) != 0; | ||||||||||||
4666 | const bool major_gte_1_5 = _major_version >= JAVA_1_5_VERSION49; | ||||||||||||
4667 | const bool major_gte_8 = _major_version
| ||||||||||||
4668 | const bool major_gte_17 = _major_version
| ||||||||||||
4669 | const bool is_initializer = (name == vmSymbols::object_initializer_name()); | ||||||||||||
4670 | |||||||||||||
4671 | bool is_illegal = false; | ||||||||||||
4672 | |||||||||||||
4673 | if (is_interface) { | ||||||||||||
4674 | if (major_gte_8) { | ||||||||||||
4675 | // Class file version is JAVA_8_VERSION or later Methods of | ||||||||||||
4676 | // interfaces may set any of the flags except ACC_PROTECTED, | ||||||||||||
4677 | // ACC_FINAL, ACC_NATIVE, and ACC_SYNCHRONIZED; they must | ||||||||||||
4678 | // have exactly one of the ACC_PUBLIC or ACC_PRIVATE flags set. | ||||||||||||
4679 | if ((is_public == is_private) || /* Only one of private and public should be true - XNOR */ | ||||||||||||
4680 | (is_native || is_protected || is_final || is_synchronized) || | ||||||||||||
4681 | // If a specific method of a class or interface has its | ||||||||||||
4682 | // ACC_ABSTRACT flag set, it must not have any of its | ||||||||||||
4683 | // ACC_FINAL, ACC_NATIVE, ACC_PRIVATE, ACC_STATIC, | ||||||||||||
4684 | // ACC_STRICT, or ACC_SYNCHRONIZED flags set. No need to | ||||||||||||
4685 | // check for ACC_FINAL, ACC_NATIVE or ACC_SYNCHRONIZED as | ||||||||||||
4686 | // those flags are illegal irrespective of ACC_ABSTRACT being set or not. | ||||||||||||
4687 | (is_abstract && (is_private || is_static || (!major_gte_17 && is_strict)))) { | ||||||||||||
4688 | is_illegal = true; | ||||||||||||
4689 | } | ||||||||||||
4690 | } else if (major_gte_1_5) { | ||||||||||||
4691 | // Class file version in the interval [JAVA_1_5_VERSION, JAVA_8_VERSION) | ||||||||||||
4692 | if (!is_public || is_private || is_protected || is_static || is_final || | ||||||||||||
4693 | is_synchronized || is_native || !is_abstract || is_strict) { | ||||||||||||
4694 | is_illegal = true; | ||||||||||||
4695 | } | ||||||||||||
4696 | } else { | ||||||||||||
4697 | // Class file version is pre-JAVA_1_5_VERSION | ||||||||||||
4698 | if (!is_public || is_static || is_final || is_native || !is_abstract) { | ||||||||||||
4699 | is_illegal = true; | ||||||||||||
4700 | } | ||||||||||||
4701 | } | ||||||||||||
4702 | } else { // not interface | ||||||||||||
4703 | if (has_illegal_visibility(flags)) { | ||||||||||||
4704 | is_illegal = true; | ||||||||||||
4705 | } else { | ||||||||||||
4706 | if (is_initializer
| ||||||||||||
4707 | if (is_static || is_final || is_synchronized || is_native || | ||||||||||||
4708 | is_abstract || (major_gte_1_5 && is_bridge)) { | ||||||||||||
4709 | is_illegal = true; | ||||||||||||
4710 | } | ||||||||||||
4711 | } else { // not initializer | ||||||||||||
4712 | if (is_abstract
| ||||||||||||
4713 | if ((is_final || is_native || is_private || is_static || | ||||||||||||
4714 | (major_gte_1_5 && (is_synchronized || (!major_gte_17 && is_strict))))) { | ||||||||||||
4715 | is_illegal = true; | ||||||||||||
4716 | } | ||||||||||||
4717 | } | ||||||||||||
4718 | } | ||||||||||||
4719 | } | ||||||||||||
4720 | } | ||||||||||||
4721 | |||||||||||||
4722 | if (is_illegal
| ||||||||||||
4723 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
4724 | Exceptions::fthrow( | ||||||||||||
4725 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4725, | ||||||||||||
4726 | vmSymbols::java_lang_ClassFormatError(), | ||||||||||||
4727 | "Method %s in class %s has illegal modifiers: 0x%X", | ||||||||||||
4728 | name->as_C_string(), _class_name->as_C_string(), flags); | ||||||||||||
4729 | return; | ||||||||||||
4730 | } | ||||||||||||
4731 | } | ||||||||||||
4732 | |||||||||||||
4733 | void ClassFileParser::verify_legal_utf8(const unsigned char* buffer, | ||||||||||||
4734 | int length, | ||||||||||||
4735 | TRAPSJavaThread* __the_thread__) const { | ||||||||||||
4736 | assert(_need_verify, "only called when _need_verify is true")do { if (!(_need_verify)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4736, "assert(" "_need_verify" ") failed", "only called when _need_verify is true" ); ::breakpoint(); } } while (0); | ||||||||||||
4737 | if (!UTF8::is_legal_utf8(buffer, length, _major_version <= 47)) { | ||||||||||||
4738 | classfile_parse_error("Illegal UTF8 string in constant pool in class file %s", THREAD__the_thread__); | ||||||||||||
4739 | } | ||||||||||||
4740 | } | ||||||||||||
4741 | |||||||||||||
4742 | // Unqualified names may not contain the characters '.', ';', '[', or '/'. | ||||||||||||
4743 | // In class names, '/' separates unqualified names. This is verified in this function also. | ||||||||||||
4744 | // Method names also may not contain the characters '<' or '>', unless <init> | ||||||||||||
4745 | // or <clinit>. Note that method names may not be <init> or <clinit> in this | ||||||||||||
4746 | // method. Because these names have been checked as special cases before | ||||||||||||
4747 | // calling this method in verify_legal_method_name. | ||||||||||||
4748 | // | ||||||||||||
4749 | // This method is also called from the modular system APIs in modules.cpp | ||||||||||||
4750 | // to verify the validity of module and package names. | ||||||||||||
4751 | bool ClassFileParser::verify_unqualified_name(const char* name, | ||||||||||||
4752 | unsigned int length, | ||||||||||||
4753 | int type) { | ||||||||||||
4754 | if (length == 0) return false; // Must have at least one char. | ||||||||||||
4755 | for (const char* p = name; p != name + length; p++) { | ||||||||||||
4756 | switch(*p) { | ||||||||||||
4757 | case JVM_SIGNATURE_DOT: | ||||||||||||
4758 | case JVM_SIGNATURE_ENDCLASS: | ||||||||||||
4759 | case JVM_SIGNATURE_ARRAY: | ||||||||||||
4760 | // do not permit '.', ';', or '[' | ||||||||||||
4761 | return false; | ||||||||||||
4762 | case JVM_SIGNATURE_SLASH: | ||||||||||||
4763 | // check for '//' or leading or trailing '/' which are not legal | ||||||||||||
4764 | // unqualified name must not be empty | ||||||||||||
4765 | if (type == ClassFileParser::LegalClass) { | ||||||||||||
4766 | if (p == name || p+1 >= name+length || | ||||||||||||
4767 | *(p+1) == JVM_SIGNATURE_SLASH) { | ||||||||||||
4768 | return false; | ||||||||||||
4769 | } | ||||||||||||
4770 | } else { | ||||||||||||
4771 | return false; // do not permit '/' unless it's class name | ||||||||||||
4772 | } | ||||||||||||
4773 | break; | ||||||||||||
4774 | case JVM_SIGNATURE_SPECIAL: | ||||||||||||
4775 | case JVM_SIGNATURE_ENDSPECIAL: | ||||||||||||
4776 | // do not permit '<' or '>' in method names | ||||||||||||
4777 | if (type == ClassFileParser::LegalMethod) { | ||||||||||||
4778 | return false; | ||||||||||||
4779 | } | ||||||||||||
4780 | } | ||||||||||||
4781 | } | ||||||||||||
4782 | return true; | ||||||||||||
4783 | } | ||||||||||||
4784 | |||||||||||||
4785 | // Take pointer to a UTF8 byte string (not NUL-terminated). | ||||||||||||
4786 | // Skip over the longest part of the string that could | ||||||||||||
4787 | // be taken as a fieldname. Allow non-trailing '/'s if slash_ok is true. | ||||||||||||
4788 | // Return a pointer to just past the fieldname. | ||||||||||||
4789 | // Return NULL if no fieldname at all was found, or in the case of slash_ok | ||||||||||||
4790 | // being true, we saw consecutive slashes (meaning we were looking for a | ||||||||||||
4791 | // qualified path but found something that was badly-formed). | ||||||||||||
4792 | static const char* skip_over_field_name(const char* const name, | ||||||||||||
4793 | bool slash_ok, | ||||||||||||
4794 | unsigned int length) { | ||||||||||||
4795 | const char* p; | ||||||||||||
4796 | jboolean last_is_slash = false; | ||||||||||||
4797 | jboolean not_first_ch = false; | ||||||||||||
4798 | |||||||||||||
4799 | for (p = name; p != name + length; not_first_ch = true) { | ||||||||||||
4800 | const char* old_p = p; | ||||||||||||
4801 | jchar ch = *p; | ||||||||||||
4802 | if (ch < 128) { | ||||||||||||
4803 | p++; | ||||||||||||
4804 | // quick check for ascii | ||||||||||||
4805 | if ((ch >= 'a' && ch <= 'z') || | ||||||||||||
4806 | (ch >= 'A' && ch <= 'Z') || | ||||||||||||
4807 | (ch == '_' || ch == '$') || | ||||||||||||
4808 | (not_first_ch && ch >= '0' && ch <= '9')) { | ||||||||||||
4809 | last_is_slash = false; | ||||||||||||
4810 | continue; | ||||||||||||
4811 | } | ||||||||||||
4812 | if (slash_ok && ch == JVM_SIGNATURE_SLASH) { | ||||||||||||
4813 | if (last_is_slash) { | ||||||||||||
4814 | return NULL__null; // Don't permit consecutive slashes | ||||||||||||
4815 | } | ||||||||||||
4816 | last_is_slash = true; | ||||||||||||
4817 | continue; | ||||||||||||
4818 | } | ||||||||||||
4819 | } | ||||||||||||
4820 | else { | ||||||||||||
4821 | jint unicode_ch; | ||||||||||||
4822 | char* tmp_p = UTF8::next_character(p, &unicode_ch); | ||||||||||||
4823 | p = tmp_p; | ||||||||||||
4824 | last_is_slash = false; | ||||||||||||
4825 | // Check if ch is Java identifier start or is Java identifier part | ||||||||||||
4826 | // 4672820: call java.lang.Character methods directly without generating separate tables. | ||||||||||||
4827 | EXCEPTION_MARKExceptionMark __em; JavaThread* __the_thread__ = __em.thread( );; | ||||||||||||
4828 | // return value | ||||||||||||
4829 | JavaValue result(T_BOOLEAN); | ||||||||||||
4830 | // Set up the arguments to isJavaIdentifierStart or isJavaIdentifierPart | ||||||||||||
4831 | JavaCallArguments args; | ||||||||||||
4832 | args.push_int(unicode_ch); | ||||||||||||
4833 | |||||||||||||
4834 | if (not_first_ch) { | ||||||||||||
4835 | // public static boolean isJavaIdentifierPart(char ch); | ||||||||||||
4836 | JavaCalls::call_static(&result, | ||||||||||||
4837 | vmClasses::Character_klass(), | ||||||||||||
4838 | vmSymbols::isJavaIdentifierPart_name(), | ||||||||||||
4839 | vmSymbols::int_bool_signature(), | ||||||||||||
4840 | &args, | ||||||||||||
4841 | THREAD__the_thread__); | ||||||||||||
4842 | } else { | ||||||||||||
4843 | // public static boolean isJavaIdentifierStart(char ch); | ||||||||||||
4844 | JavaCalls::call_static(&result, | ||||||||||||
4845 | vmClasses::Character_klass(), | ||||||||||||
4846 | vmSymbols::isJavaIdentifierStart_name(), | ||||||||||||
4847 | vmSymbols::int_bool_signature(), | ||||||||||||
4848 | &args, | ||||||||||||
4849 | THREAD__the_thread__); | ||||||||||||
4850 | } | ||||||||||||
4851 | if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) { | ||||||||||||
4852 | CLEAR_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_exception( )); | ||||||||||||
4853 | return NULL__null; | ||||||||||||
4854 | } | ||||||||||||
4855 | if(result.get_jboolean()) { | ||||||||||||
4856 | continue; | ||||||||||||
4857 | } | ||||||||||||
4858 | } | ||||||||||||
4859 | return (not_first_ch) ? old_p : NULL__null; | ||||||||||||
4860 | } | ||||||||||||
4861 | return (not_first_ch && !last_is_slash) ? p : NULL__null; | ||||||||||||
4862 | } | ||||||||||||
4863 | |||||||||||||
4864 | // Take pointer to a UTF8 byte string (not NUL-terminated). | ||||||||||||
4865 | // Skip over the longest part of the string that could | ||||||||||||
4866 | // be taken as a field signature. Allow "void" if void_ok. | ||||||||||||
4867 | // Return a pointer to just past the signature. | ||||||||||||
4868 | // Return NULL if no legal signature is found. | ||||||||||||
4869 | const char* ClassFileParser::skip_over_field_signature(const char* signature, | ||||||||||||
4870 | bool void_ok, | ||||||||||||
4871 | unsigned int length, | ||||||||||||
4872 | TRAPSJavaThread* __the_thread__) const { | ||||||||||||
4873 | unsigned int array_dim = 0; | ||||||||||||
4874 | while (length > 0) { | ||||||||||||
4875 | switch (signature[0]) { | ||||||||||||
4876 | case JVM_SIGNATURE_VOID: if (!void_ok) { return NULL__null; } | ||||||||||||
4877 | case JVM_SIGNATURE_BOOLEAN: | ||||||||||||
4878 | case JVM_SIGNATURE_BYTE: | ||||||||||||
4879 | case JVM_SIGNATURE_CHAR: | ||||||||||||
4880 | case JVM_SIGNATURE_SHORT: | ||||||||||||
4881 | case JVM_SIGNATURE_INT: | ||||||||||||
4882 | case JVM_SIGNATURE_FLOAT: | ||||||||||||
4883 | case JVM_SIGNATURE_LONG: | ||||||||||||
4884 | case JVM_SIGNATURE_DOUBLE: | ||||||||||||
4885 | return signature + 1; | ||||||||||||
4886 | case JVM_SIGNATURE_CLASS: { | ||||||||||||
4887 | if (_major_version < JAVA_1_5_VERSION49) { | ||||||||||||
4888 | // Skip over the class name if one is there | ||||||||||||
4889 | const char* const p = skip_over_field_name(signature + 1, true, --length); | ||||||||||||
4890 | |||||||||||||
4891 | // The next character better be a semicolon | ||||||||||||
4892 | if (p && (p - signature) > 1 && p[0] == JVM_SIGNATURE_ENDCLASS) { | ||||||||||||
4893 | return p + 1; | ||||||||||||
4894 | } | ||||||||||||
4895 | } | ||||||||||||
4896 | else { | ||||||||||||
4897 | // Skip leading 'L' and ignore first appearance of ';' | ||||||||||||
4898 | signature++; | ||||||||||||
4899 | const char* c = (const char*) memchr(signature, JVM_SIGNATURE_ENDCLASS, length - 1); | ||||||||||||
4900 | // Format check signature | ||||||||||||
4901 | if (c != NULL__null) { | ||||||||||||
4902 | int newlen = c - (char*) signature; | ||||||||||||
4903 | bool legal = verify_unqualified_name(signature, newlen, LegalClass); | ||||||||||||
4904 | if (!legal) { | ||||||||||||
4905 | classfile_parse_error("Class name is empty or contains illegal character " | ||||||||||||
4906 | "in descriptor in class file %s", | ||||||||||||
4907 | THREAD__the_thread__); | ||||||||||||
4908 | return NULL__null; | ||||||||||||
4909 | } | ||||||||||||
4910 | return signature + newlen + 1; | ||||||||||||
4911 | } | ||||||||||||
4912 | } | ||||||||||||
4913 | return NULL__null; | ||||||||||||
4914 | } | ||||||||||||
4915 | case JVM_SIGNATURE_ARRAY: | ||||||||||||
4916 | array_dim++; | ||||||||||||
4917 | if (array_dim > 255) { | ||||||||||||
4918 | // 4277370: array descriptor is valid only if it represents 255 or fewer dimensions. | ||||||||||||
4919 | classfile_parse_error("Array type descriptor has more than 255 dimensions in class file %s", THREAD__the_thread__); | ||||||||||||
4920 | return NULL__null; | ||||||||||||
4921 | } | ||||||||||||
4922 | // The rest of what's there better be a legal signature | ||||||||||||
4923 | signature++; | ||||||||||||
4924 | length--; | ||||||||||||
4925 | void_ok = false; | ||||||||||||
4926 | break; | ||||||||||||
4927 | default: | ||||||||||||
4928 | return NULL__null; | ||||||||||||
4929 | } | ||||||||||||
4930 | } | ||||||||||||
4931 | return NULL__null; | ||||||||||||
4932 | } | ||||||||||||
4933 | |||||||||||||
4934 | // Checks if name is a legal class name. | ||||||||||||
4935 | void ClassFileParser::verify_legal_class_name(const Symbol* name, TRAPSJavaThread* __the_thread__) const { | ||||||||||||
4936 | if (!_need_verify || _relax_verify) { return; } | ||||||||||||
4937 | |||||||||||||
4938 | assert(name->refcount() > 0, "symbol must be kept alive")do { if (!(name->refcount() > 0)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4938, "assert(" "name->refcount() > 0" ") failed", "symbol must be kept alive" ); ::breakpoint(); } } while (0); | ||||||||||||
4939 | char* bytes = (char*)name->bytes(); | ||||||||||||
4940 | unsigned int length = name->utf8_length(); | ||||||||||||
4941 | bool legal = false; | ||||||||||||
4942 | |||||||||||||
4943 | if (length > 0) { | ||||||||||||
4944 | const char* p; | ||||||||||||
4945 | if (bytes[0] == JVM_SIGNATURE_ARRAY) { | ||||||||||||
4946 | p = skip_over_field_signature(bytes, false, length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
4947 | legal = (p != NULL__null) && ((p - bytes) == (int)length); | ||||||||||||
4948 | } else if (_major_version < JAVA_1_5_VERSION49) { | ||||||||||||
4949 | if (bytes[0] != JVM_SIGNATURE_SPECIAL) { | ||||||||||||
4950 | p = skip_over_field_name(bytes, true, length); | ||||||||||||
4951 | legal = (p != NULL__null) && ((p - bytes) == (int)length); | ||||||||||||
4952 | } | ||||||||||||
4953 | } else { | ||||||||||||
4954 | // 4900761: relax the constraints based on JSR202 spec | ||||||||||||
4955 | // Class names may be drawn from the entire Unicode character set. | ||||||||||||
4956 | // Identifiers between '/' must be unqualified names. | ||||||||||||
4957 | // The utf8 string has been verified when parsing cpool entries. | ||||||||||||
4958 | legal = verify_unqualified_name(bytes, length, LegalClass); | ||||||||||||
4959 | } | ||||||||||||
4960 | } | ||||||||||||
4961 | if (!legal) { | ||||||||||||
4962 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
4963 | assert(_class_name != NULL, "invariant")do { if (!(_class_name != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4963, "assert(" "_class_name != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
4964 | Exceptions::fthrow( | ||||||||||||
4965 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4965, | ||||||||||||
4966 | vmSymbols::java_lang_ClassFormatError(), | ||||||||||||
4967 | "Illegal class name \"%.*s\" in class file %s", length, bytes, | ||||||||||||
4968 | _class_name->as_C_string() | ||||||||||||
4969 | ); | ||||||||||||
4970 | return; | ||||||||||||
4971 | } | ||||||||||||
4972 | } | ||||||||||||
4973 | |||||||||||||
4974 | // Checks if name is a legal field name. | ||||||||||||
4975 | void ClassFileParser::verify_legal_field_name(const Symbol* name, TRAPSJavaThread* __the_thread__) const { | ||||||||||||
4976 | if (!_need_verify || _relax_verify) { return; } | ||||||||||||
4977 | |||||||||||||
4978 | char* bytes = (char*)name->bytes(); | ||||||||||||
4979 | unsigned int length = name->utf8_length(); | ||||||||||||
4980 | bool legal = false; | ||||||||||||
4981 | |||||||||||||
4982 | if (length > 0) { | ||||||||||||
4983 | if (_major_version < JAVA_1_5_VERSION49) { | ||||||||||||
4984 | if (bytes[0] != JVM_SIGNATURE_SPECIAL) { | ||||||||||||
4985 | const char* p = skip_over_field_name(bytes, false, length); | ||||||||||||
4986 | legal = (p != NULL__null) && ((p - bytes) == (int)length); | ||||||||||||
4987 | } | ||||||||||||
4988 | } else { | ||||||||||||
4989 | // 4881221: relax the constraints based on JSR202 spec | ||||||||||||
4990 | legal = verify_unqualified_name(bytes, length, LegalField); | ||||||||||||
4991 | } | ||||||||||||
4992 | } | ||||||||||||
4993 | |||||||||||||
4994 | if (!legal) { | ||||||||||||
4995 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
4996 | assert(_class_name != NULL, "invariant")do { if (!(_class_name != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4996, "assert(" "_class_name != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
4997 | Exceptions::fthrow( | ||||||||||||
4998 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 4998, | ||||||||||||
4999 | vmSymbols::java_lang_ClassFormatError(), | ||||||||||||
5000 | "Illegal field name \"%.*s\" in class %s", length, bytes, | ||||||||||||
5001 | _class_name->as_C_string() | ||||||||||||
5002 | ); | ||||||||||||
5003 | return; | ||||||||||||
5004 | } | ||||||||||||
5005 | } | ||||||||||||
5006 | |||||||||||||
5007 | // Checks if name is a legal method name. | ||||||||||||
5008 | void ClassFileParser::verify_legal_method_name(const Symbol* name, TRAPSJavaThread* __the_thread__) const { | ||||||||||||
5009 | if (!_need_verify || _relax_verify) { return; } | ||||||||||||
5010 | |||||||||||||
5011 | assert(name != NULL, "method name is null")do { if (!(name != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5011, "assert(" "name != __null" ") failed", "method name is null" ); ::breakpoint(); } } while (0); | ||||||||||||
5012 | char* bytes = (char*)name->bytes(); | ||||||||||||
5013 | unsigned int length = name->utf8_length(); | ||||||||||||
5014 | bool legal = false; | ||||||||||||
5015 | |||||||||||||
5016 | if (length > 0) { | ||||||||||||
5017 | if (bytes[0] == JVM_SIGNATURE_SPECIAL) { | ||||||||||||
5018 | if (name == vmSymbols::object_initializer_name() || name == vmSymbols::class_initializer_name()) { | ||||||||||||
5019 | legal = true; | ||||||||||||
5020 | } | ||||||||||||
5021 | } else if (_major_version < JAVA_1_5_VERSION49) { | ||||||||||||
5022 | const char* p; | ||||||||||||
5023 | p = skip_over_field_name(bytes, false, length); | ||||||||||||
5024 | legal = (p != NULL__null) && ((p - bytes) == (int)length); | ||||||||||||
5025 | } else { | ||||||||||||
5026 | // 4881221: relax the constraints based on JSR202 spec | ||||||||||||
5027 | legal = verify_unqualified_name(bytes, length, LegalMethod); | ||||||||||||
5028 | } | ||||||||||||
5029 | } | ||||||||||||
5030 | |||||||||||||
5031 | if (!legal) { | ||||||||||||
5032 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
5033 | assert(_class_name != NULL, "invariant")do { if (!(_class_name != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5033, "assert(" "_class_name != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5034 | Exceptions::fthrow( | ||||||||||||
5035 | THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5035, | ||||||||||||
5036 | vmSymbols::java_lang_ClassFormatError(), | ||||||||||||
5037 | "Illegal method name \"%.*s\" in class %s", length, bytes, | ||||||||||||
5038 | _class_name->as_C_string() | ||||||||||||
5039 | ); | ||||||||||||
5040 | return; | ||||||||||||
5041 | } | ||||||||||||
5042 | } | ||||||||||||
5043 | |||||||||||||
5044 | |||||||||||||
5045 | // Checks if signature is a legal field signature. | ||||||||||||
5046 | void ClassFileParser::verify_legal_field_signature(const Symbol* name, | ||||||||||||
5047 | const Symbol* signature, | ||||||||||||
5048 | TRAPSJavaThread* __the_thread__) const { | ||||||||||||
5049 | if (!_need_verify) { return; } | ||||||||||||
5050 | |||||||||||||
5051 | const char* const bytes = (const char* const)signature->bytes(); | ||||||||||||
5052 | const unsigned int length = signature->utf8_length(); | ||||||||||||
5053 | const char* const p = skip_over_field_signature(bytes, false, length, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5054 | |||||||||||||
5055 | if (p == NULL__null || (p - bytes) != (int)length) { | ||||||||||||
5056 | throwIllegalSignature("Field", name, signature, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5057 | } | ||||||||||||
5058 | } | ||||||||||||
5059 | |||||||||||||
5060 | // Check that the signature is compatible with the method name. For example, | ||||||||||||
5061 | // check that <init> has a void signature. | ||||||||||||
5062 | void ClassFileParser::verify_legal_name_with_signature(const Symbol* name, | ||||||||||||
5063 | const Symbol* signature, | ||||||||||||
5064 | TRAPSJavaThread* __the_thread__) const { | ||||||||||||
5065 | if (!_need_verify) { | ||||||||||||
5066 | return; | ||||||||||||
5067 | } | ||||||||||||
5068 | |||||||||||||
5069 | // Class initializers cannot have args for class format version >= 51. | ||||||||||||
5070 | if (name == vmSymbols::class_initializer_name() && | ||||||||||||
5071 | signature != vmSymbols::void_method_signature() && | ||||||||||||
5072 | _major_version >= JAVA_7_VERSION51) { | ||||||||||||
5073 | throwIllegalSignature("Method", name, signature, THREAD__the_thread__); | ||||||||||||
5074 | return; | ||||||||||||
5075 | } | ||||||||||||
5076 | |||||||||||||
5077 | int sig_length = signature->utf8_length(); | ||||||||||||
5078 | if (name->utf8_length() > 0 && | ||||||||||||
5079 | name->char_at(0) == JVM_SIGNATURE_SPECIAL && | ||||||||||||
5080 | sig_length > 0 && | ||||||||||||
5081 | signature->char_at(sig_length - 1) != JVM_SIGNATURE_VOID) { | ||||||||||||
5082 | throwIllegalSignature("Method", name, signature, THREAD__the_thread__); | ||||||||||||
5083 | } | ||||||||||||
5084 | } | ||||||||||||
5085 | |||||||||||||
5086 | // Checks if signature is a legal method signature. | ||||||||||||
5087 | // Returns number of parameters | ||||||||||||
5088 | int ClassFileParser::verify_legal_method_signature(const Symbol* name, | ||||||||||||
5089 | const Symbol* signature, | ||||||||||||
5090 | TRAPSJavaThread* __the_thread__) const { | ||||||||||||
5091 | if (!_need_verify) { | ||||||||||||
5092 | // make sure caller's args_size will be less than 0 even for non-static | ||||||||||||
5093 | // method so it will be recomputed in compute_size_of_parameters(). | ||||||||||||
5094 | return -2; | ||||||||||||
5095 | } | ||||||||||||
5096 | |||||||||||||
5097 | unsigned int args_size = 0; | ||||||||||||
5098 | const char* p = (const char*)signature->bytes(); | ||||||||||||
5099 | unsigned int length = signature->utf8_length(); | ||||||||||||
5100 | const char* nextp; | ||||||||||||
5101 | |||||||||||||
5102 | // The first character must be a '(' | ||||||||||||
5103 | if ((length > 0) && (*p++ == JVM_SIGNATURE_FUNC)) { | ||||||||||||
5104 | length--; | ||||||||||||
5105 | // Skip over legal field signatures | ||||||||||||
5106 | nextp = skip_over_field_signature(p, false, length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
5107 | while ((length > 0) && (nextp != NULL__null)) { | ||||||||||||
5108 | args_size++; | ||||||||||||
5109 | if (p[0] == 'J' || p[0] == 'D') { | ||||||||||||
5110 | args_size++; | ||||||||||||
5111 | } | ||||||||||||
5112 | length -= nextp - p; | ||||||||||||
5113 | p = nextp; | ||||||||||||
5114 | nextp = skip_over_field_signature(p, false, length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
5115 | } | ||||||||||||
5116 | // The first non-signature thing better be a ')' | ||||||||||||
5117 | if ((length > 0) && (*p++ == JVM_SIGNATURE_ENDFUNC)) { | ||||||||||||
5118 | length--; | ||||||||||||
5119 | // Now we better just have a return value | ||||||||||||
5120 | nextp = skip_over_field_signature(p, true, length, CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | ||||||||||||
5121 | if (nextp && ((int)length == (nextp - p))) { | ||||||||||||
5122 | return args_size; | ||||||||||||
5123 | } | ||||||||||||
5124 | } | ||||||||||||
5125 | } | ||||||||||||
5126 | // Report error | ||||||||||||
5127 | throwIllegalSignature("Method", name, signature, THREAD__the_thread__); | ||||||||||||
5128 | return 0; | ||||||||||||
5129 | } | ||||||||||||
5130 | |||||||||||||
5131 | int ClassFileParser::static_field_size() const { | ||||||||||||
5132 | assert(_field_info != NULL, "invariant")do { if (!(_field_info != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5132, "assert(" "_field_info != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5133 | return _field_info->_static_field_size; | ||||||||||||
5134 | } | ||||||||||||
5135 | |||||||||||||
5136 | int ClassFileParser::total_oop_map_count() const { | ||||||||||||
5137 | assert(_field_info != NULL, "invariant")do { if (!(_field_info != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5137, "assert(" "_field_info != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5138 | return _field_info->oop_map_blocks->_nonstatic_oop_map_count; | ||||||||||||
5139 | } | ||||||||||||
5140 | |||||||||||||
5141 | jint ClassFileParser::layout_size() const { | ||||||||||||
5142 | assert(_field_info != NULL, "invariant")do { if (!(_field_info != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5142, "assert(" "_field_info != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5143 | return _field_info->_instance_size; | ||||||||||||
5144 | } | ||||||||||||
5145 | |||||||||||||
5146 | static void check_methods_for_intrinsics(const InstanceKlass* ik, | ||||||||||||
5147 | const Array<Method*>* methods) { | ||||||||||||
5148 | assert(ik != NULL, "invariant")do { if (!(ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5148, "assert(" "ik != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
5149 | assert(methods != NULL, "invariant")do { if (!(methods != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5149, "assert(" "methods != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5150 | |||||||||||||
5151 | // Set up Method*::intrinsic_id as soon as we know the names of methods. | ||||||||||||
5152 | // (We used to do this lazily, but now we query it in Rewriter, | ||||||||||||
5153 | // which is eagerly done for every method, so we might as well do it now, | ||||||||||||
5154 | // when everything is fresh in memory.) | ||||||||||||
5155 | const vmSymbolID klass_id = Method::klass_id_for_intrinsics(ik); | ||||||||||||
5156 | |||||||||||||
5157 | if (klass_id != vmSymbolID::NO_SID) { | ||||||||||||
5158 | for (int j = 0; j < methods->length(); ++j) { | ||||||||||||
5159 | Method* method = methods->at(j); | ||||||||||||
5160 | method->init_intrinsic_id(klass_id); | ||||||||||||
5161 | |||||||||||||
5162 | if (CheckIntrinsics) { | ||||||||||||
5163 | // Check if an intrinsic is defined for method 'method', | ||||||||||||
5164 | // but the method is not annotated with @IntrinsicCandidate. | ||||||||||||
5165 | if (method->intrinsic_id() != vmIntrinsics::_none && | ||||||||||||
5166 | !method->intrinsic_candidate()) { | ||||||||||||
5167 | tty->print("Compiler intrinsic is defined for method [%s], " | ||||||||||||
5168 | "but the method is not annotated with @IntrinsicCandidate.%s", | ||||||||||||
5169 | method->name_and_sig_as_C_string(), | ||||||||||||
5170 | NOT_DEBUG(" Method will not be inlined.") DEBUG_ONLY(" Exiting.")" Exiting." | ||||||||||||
5171 | ); | ||||||||||||
5172 | tty->cr(); | ||||||||||||
5173 | DEBUG_ONLY(vm_exit(1))vm_exit(1); | ||||||||||||
5174 | } | ||||||||||||
5175 | // Check is the method 'method' is annotated with @IntrinsicCandidate, | ||||||||||||
5176 | // but there is no intrinsic available for it. | ||||||||||||
5177 | if (method->intrinsic_candidate() && | ||||||||||||
5178 | method->intrinsic_id() == vmIntrinsics::_none) { | ||||||||||||
5179 | tty->print("Method [%s] is annotated with @IntrinsicCandidate, " | ||||||||||||
5180 | "but no compiler intrinsic is defined for the method.%s", | ||||||||||||
5181 | method->name_and_sig_as_C_string(), | ||||||||||||
5182 | NOT_DEBUG("") DEBUG_ONLY(" Exiting.")" Exiting." | ||||||||||||
5183 | ); | ||||||||||||
5184 | tty->cr(); | ||||||||||||
5185 | DEBUG_ONLY(vm_exit(1))vm_exit(1); | ||||||||||||
5186 | } | ||||||||||||
5187 | } | ||||||||||||
5188 | } // end for | ||||||||||||
5189 | |||||||||||||
5190 | #ifdef ASSERT1 | ||||||||||||
5191 | if (CheckIntrinsics) { | ||||||||||||
5192 | // Check for orphan methods in the current class. A method m | ||||||||||||
5193 | // of a class C is orphan if an intrinsic is defined for method m, | ||||||||||||
5194 | // but class C does not declare m. | ||||||||||||
5195 | // The check is potentially expensive, therefore it is available | ||||||||||||
5196 | // only in debug builds. | ||||||||||||
5197 | |||||||||||||
5198 | for (auto id : EnumRange<vmIntrinsicID>{}) { | ||||||||||||
5199 | if (vmIntrinsics::_compiledLambdaForm == id) { | ||||||||||||
5200 | // The _compiledLamdbdaForm intrinsic is a special marker for bytecode | ||||||||||||
5201 | // generated for the JVM from a LambdaForm and therefore no method | ||||||||||||
5202 | // is defined for it. | ||||||||||||
5203 | continue; | ||||||||||||
5204 | } | ||||||||||||
5205 | if (vmIntrinsics::_blackhole == id) { | ||||||||||||
5206 | // The _blackhole intrinsic is a special marker. No explicit method | ||||||||||||
5207 | // is defined for it. | ||||||||||||
5208 | continue; | ||||||||||||
5209 | } | ||||||||||||
5210 | |||||||||||||
5211 | if (vmIntrinsics::class_for(id) == klass_id) { | ||||||||||||
5212 | // Check if the current class contains a method with the same | ||||||||||||
5213 | // name, flags, signature. | ||||||||||||
5214 | bool match = false; | ||||||||||||
5215 | for (int j = 0; j < methods->length(); ++j) { | ||||||||||||
5216 | const Method* method = methods->at(j); | ||||||||||||
5217 | if (method->intrinsic_id() == id) { | ||||||||||||
5218 | match = true; | ||||||||||||
5219 | break; | ||||||||||||
5220 | } | ||||||||||||
5221 | } | ||||||||||||
5222 | |||||||||||||
5223 | if (!match) { | ||||||||||||
5224 | char buf[1000]; | ||||||||||||
5225 | tty->print("Compiler intrinsic is defined for method [%s], " | ||||||||||||
5226 | "but the method is not available in class [%s].%s", | ||||||||||||
5227 | vmIntrinsics::short_name_as_C_string(id, buf, sizeof(buf)), | ||||||||||||
5228 | ik->name()->as_C_string(), | ||||||||||||
5229 | NOT_DEBUG("") DEBUG_ONLY(" Exiting.")" Exiting." | ||||||||||||
5230 | ); | ||||||||||||
5231 | tty->cr(); | ||||||||||||
5232 | DEBUG_ONLY(vm_exit(1))vm_exit(1); | ||||||||||||
5233 | } | ||||||||||||
5234 | } | ||||||||||||
5235 | } // end for | ||||||||||||
5236 | } // CheckIntrinsics | ||||||||||||
5237 | #endif // ASSERT | ||||||||||||
5238 | } | ||||||||||||
5239 | } | ||||||||||||
5240 | |||||||||||||
5241 | InstanceKlass* ClassFileParser::create_instance_klass(bool changed_by_loadhook, | ||||||||||||
5242 | const ClassInstanceInfo& cl_inst_info, | ||||||||||||
5243 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
5244 | if (_klass != NULL__null) { | ||||||||||||
5245 | return _klass; | ||||||||||||
5246 | } | ||||||||||||
5247 | |||||||||||||
5248 | InstanceKlass* const ik = | ||||||||||||
5249 | InstanceKlass::allocate_instance_klass(*this, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
5250 | |||||||||||||
5251 | if (is_hidden()) { | ||||||||||||
5252 | mangle_hidden_class_name(ik); | ||||||||||||
5253 | } | ||||||||||||
5254 | |||||||||||||
5255 | fill_instance_klass(ik, changed_by_loadhook, cl_inst_info, CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); | ||||||||||||
5256 | |||||||||||||
5257 | assert(_klass == ik, "invariant")do { if (!(_klass == ik)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5257, "assert(" "_klass == ik" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
5258 | |||||||||||||
5259 | return ik; | ||||||||||||
5260 | } | ||||||||||||
5261 | |||||||||||||
5262 | void ClassFileParser::fill_instance_klass(InstanceKlass* ik, | ||||||||||||
5263 | bool changed_by_loadhook, | ||||||||||||
5264 | const ClassInstanceInfo& cl_inst_info, | ||||||||||||
5265 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
5266 | assert(ik != NULL, "invariant")do { if (!(ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5266, "assert(" "ik != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
5267 | |||||||||||||
5268 | // Set name and CLD before adding to CLD | ||||||||||||
5269 | ik->set_class_loader_data(_loader_data); | ||||||||||||
5270 | ik->set_name(_class_name); | ||||||||||||
5271 | |||||||||||||
5272 | // Add all classes to our internal class loader list here, | ||||||||||||
5273 | // including classes in the bootstrap (NULL) class loader. | ||||||||||||
5274 | const bool publicize = !is_internal(); | ||||||||||||
5275 | |||||||||||||
5276 | _loader_data->add_class(ik, publicize); | ||||||||||||
5277 | |||||||||||||
5278 | set_klass_to_deallocate(ik); | ||||||||||||
5279 | |||||||||||||
5280 | assert(_field_info != NULL, "invariant")do { if (!(_field_info != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5280, "assert(" "_field_info != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5281 | assert(ik->static_field_size() == _field_info->_static_field_size, "sanity")do { if (!(ik->static_field_size() == _field_info->_static_field_size )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5281, "assert(" "ik->static_field_size() == _field_info->_static_field_size" ") failed", "sanity"); ::breakpoint(); } } while (0); | ||||||||||||
5282 | assert(ik->nonstatic_oop_map_count() == _field_info->oop_map_blocks->_nonstatic_oop_map_count,do { if (!(ik->nonstatic_oop_map_count() == _field_info-> oop_map_blocks->_nonstatic_oop_map_count)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5283, "assert(" "ik->nonstatic_oop_map_count() == _field_info->oop_map_blocks->_nonstatic_oop_map_count" ") failed", "sanity"); ::breakpoint(); } } while (0) | ||||||||||||
5283 | "sanity")do { if (!(ik->nonstatic_oop_map_count() == _field_info-> oop_map_blocks->_nonstatic_oop_map_count)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5283, "assert(" "ik->nonstatic_oop_map_count() == _field_info->oop_map_blocks->_nonstatic_oop_map_count" ") failed", "sanity"); ::breakpoint(); } } while (0); | ||||||||||||
5284 | |||||||||||||
5285 | assert(ik->is_instance_klass(), "sanity")do { if (!(ik->is_instance_klass())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5285, "assert(" "ik->is_instance_klass()" ") failed", "sanity" ); ::breakpoint(); } } while (0); | ||||||||||||
5286 | assert(ik->size_helper() == _field_info->_instance_size, "sanity")do { if (!(ik->size_helper() == _field_info->_instance_size )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5286, "assert(" "ik->size_helper() == _field_info->_instance_size" ") failed", "sanity"); ::breakpoint(); } } while (0); | ||||||||||||
5287 | |||||||||||||
5288 | // Fill in information already parsed | ||||||||||||
5289 | ik->set_should_verify_class(_need_verify); | ||||||||||||
5290 | |||||||||||||
5291 | // Not yet: supers are done below to support the new subtype-checking fields | ||||||||||||
5292 | ik->set_nonstatic_field_size(_field_info->_nonstatic_field_size); | ||||||||||||
5293 | ik->set_has_nonstatic_fields(_field_info->_has_nonstatic_fields); | ||||||||||||
5294 | assert(_fac != NULL, "invariant")do { if (!(_fac != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5294, "assert(" "_fac != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
5295 | ik->set_static_oop_field_count(_fac->count[STATIC_OOP]); | ||||||||||||
5296 | |||||||||||||
5297 | // this transfers ownership of a lot of arrays from | ||||||||||||
5298 | // the parser onto the InstanceKlass* | ||||||||||||
5299 | apply_parsed_class_metadata(ik, _java_fields_count); | ||||||||||||
5300 | |||||||||||||
5301 | // can only set dynamic nest-host after static nest information is set | ||||||||||||
5302 | if (cl_inst_info.dynamic_nest_host() != NULL__null) { | ||||||||||||
5303 | ik->set_nest_host(cl_inst_info.dynamic_nest_host()); | ||||||||||||
5304 | } | ||||||||||||
5305 | |||||||||||||
5306 | // note that is not safe to use the fields in the parser from this point on | ||||||||||||
5307 | assert(NULL == _cp, "invariant")do { if (!(__null == _cp)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5307, "assert(" "__null == _cp" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
5308 | assert(NULL == _fields, "invariant")do { if (!(__null == _fields)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5308, "assert(" "__null == _fields" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5309 | assert(NULL == _methods, "invariant")do { if (!(__null == _methods)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5309, "assert(" "__null == _methods" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5310 | assert(NULL == _inner_classes, "invariant")do { if (!(__null == _inner_classes)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5310, "assert(" "__null == _inner_classes" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5311 | assert(NULL == _nest_members, "invariant")do { if (!(__null == _nest_members)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5311, "assert(" "__null == _nest_members" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5312 | assert(NULL == _combined_annotations, "invariant")do { if (!(__null == _combined_annotations)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5312, "assert(" "__null == _combined_annotations" ") failed" , "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
5313 | assert(NULL == _record_components, "invariant")do { if (!(__null == _record_components)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5313, "assert(" "__null == _record_components" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5314 | assert(NULL == _permitted_subclasses, "invariant")do { if (!(__null == _permitted_subclasses)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5314, "assert(" "__null == _permitted_subclasses" ") failed" , "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
5315 | |||||||||||||
5316 | if (_has_final_method) { | ||||||||||||
5317 | ik->set_has_final_method(); | ||||||||||||
5318 | } | ||||||||||||
5319 | |||||||||||||
5320 | ik->copy_method_ordering(_method_ordering, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5321 | // The InstanceKlass::_methods_jmethod_ids cache | ||||||||||||
5322 | // is managed on the assumption that the initial cache | ||||||||||||
5323 | // size is equal to the number of methods in the class. If | ||||||||||||
5324 | // that changes, then InstanceKlass::idnum_can_increment() | ||||||||||||
5325 | // has to be changed accordingly. | ||||||||||||
5326 | ik->set_initial_method_idnum(ik->methods()->length()); | ||||||||||||
5327 | |||||||||||||
5328 | ik->set_this_class_index(_this_class_index); | ||||||||||||
5329 | |||||||||||||
5330 | if (_is_hidden) { | ||||||||||||
5331 | // _this_class_index is a CONSTANT_Class entry that refers to this | ||||||||||||
5332 | // hidden class itself. If this class needs to refer to its own methods | ||||||||||||
5333 | // or fields, it would use a CONSTANT_MethodRef, etc, which would reference | ||||||||||||
5334 | // _this_class_index. However, because this class is hidden (it's | ||||||||||||
5335 | // not stored in SystemDictionary), _this_class_index cannot be resolved | ||||||||||||
5336 | // with ConstantPool::klass_at_impl, which does a SystemDictionary lookup. | ||||||||||||
5337 | // Therefore, we must eagerly resolve _this_class_index now. | ||||||||||||
5338 | ik->constants()->klass_at_put(_this_class_index, ik); | ||||||||||||
5339 | } | ||||||||||||
5340 | |||||||||||||
5341 | ik->set_minor_version(_minor_version); | ||||||||||||
5342 | ik->set_major_version(_major_version); | ||||||||||||
5343 | ik->set_has_nonstatic_concrete_methods(_has_nonstatic_concrete_methods); | ||||||||||||
5344 | ik->set_declares_nonstatic_concrete_methods(_declares_nonstatic_concrete_methods); | ||||||||||||
5345 | |||||||||||||
5346 | if (_is_hidden) { | ||||||||||||
5347 | ik->set_is_hidden(); | ||||||||||||
5348 | } | ||||||||||||
5349 | |||||||||||||
5350 | // Set PackageEntry for this_klass | ||||||||||||
5351 | oop cl = ik->class_loader(); | ||||||||||||
5352 | Handle clh = Handle(THREAD__the_thread__, java_lang_ClassLoader::non_reflection_class_loader(cl)); | ||||||||||||
5353 | ClassLoaderData* cld = ClassLoaderData::class_loader_data_or_null(clh()); | ||||||||||||
5354 | ik->set_package(cld, NULL__null, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5355 | |||||||||||||
5356 | const Array<Method*>* const methods = ik->methods(); | ||||||||||||
5357 | assert(methods != NULL, "invariant")do { if (!(methods != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5357, "assert(" "methods != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5358 | const int methods_len = methods->length(); | ||||||||||||
5359 | |||||||||||||
5360 | check_methods_for_intrinsics(ik, methods); | ||||||||||||
5361 | |||||||||||||
5362 | // Fill in field values obtained by parse_classfile_attributes | ||||||||||||
5363 | if (_parsed_annotations->has_any_annotations()) { | ||||||||||||
5364 | _parsed_annotations->apply_to(ik); | ||||||||||||
5365 | } | ||||||||||||
5366 | |||||||||||||
5367 | apply_parsed_class_attributes(ik); | ||||||||||||
5368 | |||||||||||||
5369 | // Miranda methods | ||||||||||||
5370 | if ((_num_miranda_methods > 0) || | ||||||||||||
5371 | // if this class introduced new miranda methods or | ||||||||||||
5372 | (_super_klass != NULL__null && _super_klass->has_miranda_methods()) | ||||||||||||
5373 | // super class exists and this class inherited miranda methods | ||||||||||||
5374 | ) { | ||||||||||||
5375 | ik->set_has_miranda_methods(); // then set a flag | ||||||||||||
5376 | } | ||||||||||||
5377 | |||||||||||||
5378 | // Fill in information needed to compute superclasses. | ||||||||||||
5379 | ik->initialize_supers(const_cast<InstanceKlass*>(_super_klass), _transitive_interfaces, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5380 | ik->set_transitive_interfaces(_transitive_interfaces); | ||||||||||||
5381 | ik->set_local_interfaces(_local_interfaces); | ||||||||||||
5382 | _transitive_interfaces = NULL__null; | ||||||||||||
5383 | _local_interfaces = NULL__null; | ||||||||||||
5384 | |||||||||||||
5385 | // Initialize itable offset tables | ||||||||||||
5386 | klassItable::setup_itable_offset_table(ik); | ||||||||||||
5387 | |||||||||||||
5388 | // Compute transitive closure of interfaces this class implements | ||||||||||||
5389 | // Do final class setup | ||||||||||||
5390 | OopMapBlocksBuilder* oop_map_blocks = _field_info->oop_map_blocks; | ||||||||||||
5391 | if (oop_map_blocks->_nonstatic_oop_map_count > 0) { | ||||||||||||
5392 | oop_map_blocks->copy(ik->start_of_nonstatic_oop_maps()); | ||||||||||||
5393 | } | ||||||||||||
5394 | |||||||||||||
5395 | if (_has_contended_fields || _parsed_annotations->is_contended() || | ||||||||||||
5396 | ( _super_klass != NULL__null && _super_klass->has_contended_annotations())) { | ||||||||||||
5397 | ik->set_has_contended_annotations(true); | ||||||||||||
5398 | } | ||||||||||||
5399 | |||||||||||||
5400 | // Fill in has_finalizer, has_vanilla_constructor, and layout_helper | ||||||||||||
5401 | set_precomputed_flags(ik); | ||||||||||||
5402 | |||||||||||||
5403 | // check if this class can access its super class | ||||||||||||
5404 | check_super_class_access(ik, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5405 | |||||||||||||
5406 | // check if this class can access its superinterfaces | ||||||||||||
5407 | check_super_interface_access(ik, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5408 | |||||||||||||
5409 | // check if this class overrides any final method | ||||||||||||
5410 | check_final_method_override(ik, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5411 | |||||||||||||
5412 | // reject static interface methods prior to Java 8 | ||||||||||||
5413 | if (ik->is_interface() && _major_version < JAVA_8_VERSION52) { | ||||||||||||
5414 | check_illegal_static_method(ik, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5415 | } | ||||||||||||
5416 | |||||||||||||
5417 | // Obtain this_klass' module entry | ||||||||||||
5418 | ModuleEntry* module_entry = ik->module(); | ||||||||||||
5419 | assert(module_entry != NULL, "module_entry should always be set")do { if (!(module_entry != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5419, "assert(" "module_entry != __null" ") failed", "module_entry should always be set" ); ::breakpoint(); } } while (0); | ||||||||||||
5420 | |||||||||||||
5421 | // Obtain java.lang.Module | ||||||||||||
5422 | Handle module_handle(THREAD__the_thread__, module_entry->module()); | ||||||||||||
5423 | |||||||||||||
5424 | // Allocate mirror and initialize static fields | ||||||||||||
5425 | // The create_mirror() call will also call compute_modifiers() | ||||||||||||
5426 | java_lang_Class::create_mirror(ik, | ||||||||||||
5427 | Handle(THREAD__the_thread__, _loader_data->class_loader()), | ||||||||||||
5428 | module_handle, | ||||||||||||
5429 | _protection_domain, | ||||||||||||
5430 | cl_inst_info.class_data(), | ||||||||||||
5431 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5432 | |||||||||||||
5433 | assert(_all_mirandas != NULL, "invariant")do { if (!(_all_mirandas != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5433, "assert(" "_all_mirandas != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5434 | |||||||||||||
5435 | // Generate any default methods - default methods are public interface methods | ||||||||||||
5436 | // that have a default implementation. This is new with Java 8. | ||||||||||||
5437 | if (_has_nonstatic_concrete_methods) { | ||||||||||||
5438 | DefaultMethods::generate_default_methods(ik, | ||||||||||||
5439 | _all_mirandas, | ||||||||||||
5440 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5441 | } | ||||||||||||
5442 | |||||||||||||
5443 | // Add read edges to the unnamed modules of the bootstrap and app class loaders. | ||||||||||||
5444 | if (changed_by_loadhook && !module_handle.is_null() && module_entry->is_named() && | ||||||||||||
5445 | !module_entry->has_default_read_edges()) { | ||||||||||||
5446 | if (!module_entry->set_has_default_read_edges()) { | ||||||||||||
5447 | // We won a potential race | ||||||||||||
5448 | JvmtiExport::add_default_read_edges(module_handle, THREAD__the_thread__); | ||||||||||||
5449 | } | ||||||||||||
5450 | } | ||||||||||||
5451 | |||||||||||||
5452 | ClassLoadingService::notify_class_loaded(ik, false /* not shared class */); | ||||||||||||
5453 | |||||||||||||
5454 | if (!is_internal()) { | ||||||||||||
5455 | ik->print_class_load_logging(_loader_data, module_entry, _stream); | ||||||||||||
5456 | |||||||||||||
5457 | if (ik->minor_version() == JAVA_PREVIEW_MINOR_VERSION65535 && | ||||||||||||
5458 | ik->major_version() == JVM_CLASSFILE_MAJOR_VERSION63 && | ||||||||||||
5459 | log_is_enabled(Info, class, preview)(LogImpl<(LogTag::_class), (LogTag::_preview), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Info))) { | ||||||||||||
5460 | ResourceMark rm; | ||||||||||||
5461 | log_info(class, preview)(!(LogImpl<(LogTag::_class), (LogTag::_preview), (LogTag:: __NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG )>::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag ::_class), (LogTag::_preview), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Info>("Loading class %s that depends on preview features (class file version %d.65535)", | ||||||||||||
5462 | ik->external_name(), JVM_CLASSFILE_MAJOR_VERSION63); | ||||||||||||
5463 | } | ||||||||||||
5464 | |||||||||||||
5465 | if (log_is_enabled(Debug, class, resolve)(LogImpl<(LogTag::_class), (LogTag::_resolve), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Debug))) { | ||||||||||||
5466 | ResourceMark rm; | ||||||||||||
5467 | // print out the superclass. | ||||||||||||
5468 | const char * from = ik->external_name(); | ||||||||||||
5469 | if (ik->java_super() != NULL__null) { | ||||||||||||
5470 | log_debug(class, resolve)(!(LogImpl<(LogTag::_class), (LogTag::_resolve), (LogTag:: __NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG )>::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_class), (LogTag::_resolve), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("%s %s (super)", | ||||||||||||
5471 | from, | ||||||||||||
5472 | ik->java_super()->external_name()); | ||||||||||||
5473 | } | ||||||||||||
5474 | // print out each of the interface classes referred to by this class. | ||||||||||||
5475 | const Array<InstanceKlass*>* const local_interfaces = ik->local_interfaces(); | ||||||||||||
5476 | if (local_interfaces != NULL__null) { | ||||||||||||
5477 | const int length = local_interfaces->length(); | ||||||||||||
5478 | for (int i = 0; i < length; i++) { | ||||||||||||
5479 | const InstanceKlass* const k = local_interfaces->at(i); | ||||||||||||
5480 | const char * to = k->external_name(); | ||||||||||||
5481 | log_debug(class, resolve)(!(LogImpl<(LogTag::_class), (LogTag::_resolve), (LogTag:: __NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG )>::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag ::_class), (LogTag::_resolve), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Debug>("%s %s (interface)", from, to); | ||||||||||||
5482 | } | ||||||||||||
5483 | } | ||||||||||||
5484 | } | ||||||||||||
5485 | } | ||||||||||||
5486 | |||||||||||||
5487 | JFR_ONLY(INIT_ID(ik);)JfrTraceId::assign(ik); | ||||||||||||
5488 | |||||||||||||
5489 | // If we reach here, all is well. | ||||||||||||
5490 | // Now remove the InstanceKlass* from the _klass_to_deallocate field | ||||||||||||
5491 | // in order for it to not be destroyed in the ClassFileParser destructor. | ||||||||||||
5492 | set_klass_to_deallocate(NULL__null); | ||||||||||||
5493 | |||||||||||||
5494 | // it's official | ||||||||||||
5495 | set_klass(ik); | ||||||||||||
5496 | |||||||||||||
5497 | debug_only(ik->verify();)ik->verify(); | ||||||||||||
5498 | } | ||||||||||||
5499 | |||||||||||||
5500 | void ClassFileParser::update_class_name(Symbol* new_class_name) { | ||||||||||||
5501 | // Decrement the refcount in the old name, since we're clobbering it. | ||||||||||||
5502 | _class_name->decrement_refcount(); | ||||||||||||
5503 | |||||||||||||
5504 | _class_name = new_class_name; | ||||||||||||
5505 | // Increment the refcount of the new name. | ||||||||||||
5506 | // Now the ClassFileParser owns this name and will decrement in | ||||||||||||
5507 | // the destructor. | ||||||||||||
5508 | _class_name->increment_refcount(); | ||||||||||||
5509 | } | ||||||||||||
5510 | |||||||||||||
5511 | static bool relax_format_check_for(ClassLoaderData* loader_data) { | ||||||||||||
5512 | bool trusted = loader_data->is_boot_class_loader_data() || | ||||||||||||
5513 | loader_data->is_platform_class_loader_data(); | ||||||||||||
5514 | bool need_verify = | ||||||||||||
5515 | // verifyAll | ||||||||||||
5516 | (BytecodeVerificationLocal && BytecodeVerificationRemote) || | ||||||||||||
5517 | // verifyRemote | ||||||||||||
5518 | (!BytecodeVerificationLocal && BytecodeVerificationRemote && !trusted); | ||||||||||||
5519 | return !need_verify; | ||||||||||||
5520 | } | ||||||||||||
5521 | |||||||||||||
5522 | ClassFileParser::ClassFileParser(ClassFileStream* stream, | ||||||||||||
5523 | Symbol* name, | ||||||||||||
5524 | ClassLoaderData* loader_data, | ||||||||||||
5525 | const ClassLoadInfo* cl_info, | ||||||||||||
5526 | Publicity pub_level, | ||||||||||||
5527 | TRAPSJavaThread* __the_thread__) : | ||||||||||||
5528 | _stream(stream), | ||||||||||||
5529 | _class_name(NULL__null), | ||||||||||||
5530 | _loader_data(loader_data), | ||||||||||||
5531 | _is_hidden(cl_info->is_hidden()), | ||||||||||||
5532 | _can_access_vm_annotations(cl_info->can_access_vm_annotations()), | ||||||||||||
5533 | _orig_cp_size(0), | ||||||||||||
5534 | _super_klass(), | ||||||||||||
5535 | _cp(NULL__null), | ||||||||||||
5536 | _fields(NULL__null), | ||||||||||||
5537 | _methods(NULL__null), | ||||||||||||
5538 | _inner_classes(NULL__null), | ||||||||||||
5539 | _nest_members(NULL__null), | ||||||||||||
5540 | _nest_host(0), | ||||||||||||
5541 | _permitted_subclasses(NULL__null), | ||||||||||||
5542 | _record_components(NULL__null), | ||||||||||||
5543 | _local_interfaces(NULL__null), | ||||||||||||
5544 | _transitive_interfaces(NULL__null), | ||||||||||||
5545 | _combined_annotations(NULL__null), | ||||||||||||
5546 | _class_annotations(NULL__null), | ||||||||||||
5547 | _class_type_annotations(NULL__null), | ||||||||||||
5548 | _fields_annotations(NULL__null), | ||||||||||||
5549 | _fields_type_annotations(NULL__null), | ||||||||||||
5550 | _klass(NULL__null), | ||||||||||||
5551 | _klass_to_deallocate(NULL__null), | ||||||||||||
5552 | _parsed_annotations(NULL__null), | ||||||||||||
5553 | _fac(NULL__null), | ||||||||||||
5554 | _field_info(NULL__null), | ||||||||||||
5555 | _method_ordering(NULL__null), | ||||||||||||
5556 | _all_mirandas(NULL__null), | ||||||||||||
5557 | _vtable_size(0), | ||||||||||||
5558 | _itable_size(0), | ||||||||||||
5559 | _num_miranda_methods(0), | ||||||||||||
5560 | _rt(REF_NONE), | ||||||||||||
5561 | _protection_domain(cl_info->protection_domain()), | ||||||||||||
5562 | _access_flags(), | ||||||||||||
5563 | _pub_level(pub_level), | ||||||||||||
5564 | _bad_constant_seen(0), | ||||||||||||
5565 | _synthetic_flag(false), | ||||||||||||
5566 | _sde_length(false), | ||||||||||||
5567 | _sde_buffer(NULL__null), | ||||||||||||
5568 | _sourcefile_index(0), | ||||||||||||
5569 | _generic_signature_index(0), | ||||||||||||
5570 | _major_version(0), | ||||||||||||
5571 | _minor_version(0), | ||||||||||||
5572 | _this_class_index(0), | ||||||||||||
5573 | _super_class_index(0), | ||||||||||||
5574 | _itfs_len(0), | ||||||||||||
5575 | _java_fields_count(0), | ||||||||||||
5576 | _need_verify(false), | ||||||||||||
5577 | _relax_verify(false), | ||||||||||||
5578 | _has_nonstatic_concrete_methods(false), | ||||||||||||
5579 | _declares_nonstatic_concrete_methods(false), | ||||||||||||
5580 | _has_final_method(false), | ||||||||||||
5581 | _has_contended_fields(false), | ||||||||||||
5582 | _has_finalizer(false), | ||||||||||||
5583 | _has_empty_finalizer(false), | ||||||||||||
5584 | _has_vanilla_constructor(false), | ||||||||||||
5585 | _max_bootstrap_specifier_index(-1) { | ||||||||||||
5586 | |||||||||||||
5587 | _class_name = name != NULL__null ? name : vmSymbols::unknown_class_name(); | ||||||||||||
5588 | _class_name->increment_refcount(); | ||||||||||||
5589 | |||||||||||||
5590 | assert(_loader_data != NULL, "invariant")do { if (!(_loader_data != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5590, "assert(" "_loader_data != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5591 | assert(stream != NULL, "invariant")do { if (!(stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5591, "assert(" "stream != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); | ||||||||||||
5592 | assert(_stream != NULL, "invariant")do { if (!(_stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5592, "assert(" "_stream != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5593 | assert(_stream->buffer() == _stream->current(), "invariant")do { if (!(_stream->buffer() == _stream->current())) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5593, "assert(" "_stream->buffer() == _stream->current()" ") failed", "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
5594 | assert(_class_name != NULL, "invariant")do { if (!(_class_name != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5594, "assert(" "_class_name != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5595 | assert(0 == _access_flags.as_int(), "invariant")do { if (!(0 == _access_flags.as_int())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5595, "assert(" "0 == _access_flags.as_int()" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5596 | |||||||||||||
5597 | // Figure out whether we can skip format checking (matching classic VM behavior) | ||||||||||||
5598 | if (DumpSharedSpaces) { | ||||||||||||
5599 | // verify == true means it's a 'remote' class (i.e., non-boot class) | ||||||||||||
5600 | // Verification decision is based on BytecodeVerificationRemote flag | ||||||||||||
5601 | // for those classes. | ||||||||||||
5602 | _need_verify = (stream->need_verify()) ? BytecodeVerificationRemote : | ||||||||||||
5603 | BytecodeVerificationLocal; | ||||||||||||
5604 | } | ||||||||||||
5605 | else { | ||||||||||||
5606 | _need_verify = Verifier::should_verify_for(_loader_data->class_loader(), | ||||||||||||
5607 | stream->need_verify()); | ||||||||||||
5608 | } | ||||||||||||
5609 | |||||||||||||
5610 | // synch back verification state to stream | ||||||||||||
5611 | stream->set_verify(_need_verify); | ||||||||||||
5612 | |||||||||||||
5613 | // Check if verification needs to be relaxed for this class file | ||||||||||||
5614 | // Do not restrict it to jdk1.0 or jdk1.1 to maintain backward compatibility (4982376) | ||||||||||||
5615 | _relax_verify = relax_format_check_for(_loader_data); | ||||||||||||
5616 | |||||||||||||
5617 | parse_stream(stream, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5618 | |||||||||||||
5619 | post_process_parsed_stream(stream, _cp, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5620 | } | ||||||||||||
5621 | |||||||||||||
5622 | void ClassFileParser::clear_class_metadata() { | ||||||||||||
5623 | // metadata created before the instance klass is created. Must be | ||||||||||||
5624 | // deallocated if classfile parsing returns an error. | ||||||||||||
5625 | _cp = NULL__null; | ||||||||||||
5626 | _fields = NULL__null; | ||||||||||||
5627 | _methods = NULL__null; | ||||||||||||
5628 | _inner_classes = NULL__null; | ||||||||||||
5629 | _nest_members = NULL__null; | ||||||||||||
5630 | _permitted_subclasses = NULL__null; | ||||||||||||
5631 | _combined_annotations = NULL__null; | ||||||||||||
5632 | _class_annotations = _class_type_annotations = NULL__null; | ||||||||||||
5633 | _fields_annotations = _fields_type_annotations = NULL__null; | ||||||||||||
5634 | _record_components = NULL__null; | ||||||||||||
5635 | } | ||||||||||||
5636 | |||||||||||||
5637 | // Destructor to clean up | ||||||||||||
5638 | ClassFileParser::~ClassFileParser() { | ||||||||||||
5639 | _class_name->decrement_refcount(); | ||||||||||||
5640 | |||||||||||||
5641 | if (_cp != NULL__null) { | ||||||||||||
5642 | MetadataFactory::free_metadata(_loader_data, _cp); | ||||||||||||
5643 | } | ||||||||||||
5644 | if (_fields != NULL__null) { | ||||||||||||
5645 | MetadataFactory::free_array<u2>(_loader_data, _fields); | ||||||||||||
5646 | } | ||||||||||||
5647 | |||||||||||||
5648 | if (_methods != NULL__null) { | ||||||||||||
5649 | // Free methods | ||||||||||||
5650 | InstanceKlass::deallocate_methods(_loader_data, _methods); | ||||||||||||
5651 | } | ||||||||||||
5652 | |||||||||||||
5653 | // beware of the Universe::empty_blah_array!! | ||||||||||||
5654 | if (_inner_classes != NULL__null && _inner_classes != Universe::the_empty_short_array()) { | ||||||||||||
5655 | MetadataFactory::free_array<u2>(_loader_data, _inner_classes); | ||||||||||||
5656 | } | ||||||||||||
5657 | |||||||||||||
5658 | if (_nest_members != NULL__null && _nest_members != Universe::the_empty_short_array()) { | ||||||||||||
5659 | MetadataFactory::free_array<u2>(_loader_data, _nest_members); | ||||||||||||
5660 | } | ||||||||||||
5661 | |||||||||||||
5662 | if (_record_components != NULL__null) { | ||||||||||||
5663 | InstanceKlass::deallocate_record_components(_loader_data, _record_components); | ||||||||||||
5664 | } | ||||||||||||
5665 | |||||||||||||
5666 | if (_permitted_subclasses != NULL__null && _permitted_subclasses != Universe::the_empty_short_array()) { | ||||||||||||
5667 | MetadataFactory::free_array<u2>(_loader_data, _permitted_subclasses); | ||||||||||||
5668 | } | ||||||||||||
5669 | |||||||||||||
5670 | // Free interfaces | ||||||||||||
5671 | InstanceKlass::deallocate_interfaces(_loader_data, _super_klass, | ||||||||||||
5672 | _local_interfaces, _transitive_interfaces); | ||||||||||||
5673 | |||||||||||||
5674 | if (_combined_annotations != NULL__null) { | ||||||||||||
5675 | // After all annotations arrays have been created, they are installed into the | ||||||||||||
5676 | // Annotations object that will be assigned to the InstanceKlass being created. | ||||||||||||
5677 | |||||||||||||
5678 | // Deallocate the Annotations object and the installed annotations arrays. | ||||||||||||
5679 | _combined_annotations->deallocate_contents(_loader_data); | ||||||||||||
5680 | |||||||||||||
5681 | // If the _combined_annotations pointer is non-NULL, | ||||||||||||
5682 | // then the other annotations fields should have been cleared. | ||||||||||||
5683 | assert(_class_annotations == NULL, "Should have been cleared")do { if (!(_class_annotations == __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5683, "assert(" "_class_annotations == __null" ") failed", "Should have been cleared" ); ::breakpoint(); } } while (0); | ||||||||||||
5684 | assert(_class_type_annotations == NULL, "Should have been cleared")do { if (!(_class_type_annotations == __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5684, "assert(" "_class_type_annotations == __null" ") failed" , "Should have been cleared"); ::breakpoint(); } } while (0); | ||||||||||||
5685 | assert(_fields_annotations == NULL, "Should have been cleared")do { if (!(_fields_annotations == __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5685, "assert(" "_fields_annotations == __null" ") failed", "Should have been cleared"); ::breakpoint(); } } while (0); | ||||||||||||
5686 | assert(_fields_type_annotations == NULL, "Should have been cleared")do { if (!(_fields_type_annotations == __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5686, "assert(" "_fields_type_annotations == __null" ") failed" , "Should have been cleared"); ::breakpoint(); } } while (0); | ||||||||||||
5687 | } else { | ||||||||||||
5688 | // If the annotations arrays were not installed into the Annotations object, | ||||||||||||
5689 | // then they have to be deallocated explicitly. | ||||||||||||
5690 | MetadataFactory::free_array<u1>(_loader_data, _class_annotations); | ||||||||||||
5691 | MetadataFactory::free_array<u1>(_loader_data, _class_type_annotations); | ||||||||||||
5692 | Annotations::free_contents(_loader_data, _fields_annotations); | ||||||||||||
5693 | Annotations::free_contents(_loader_data, _fields_type_annotations); | ||||||||||||
5694 | } | ||||||||||||
5695 | |||||||||||||
5696 | clear_class_metadata(); | ||||||||||||
5697 | _transitive_interfaces = NULL__null; | ||||||||||||
5698 | _local_interfaces = NULL__null; | ||||||||||||
5699 | |||||||||||||
5700 | // deallocate the klass if already created. Don't directly deallocate, but add | ||||||||||||
5701 | // to the deallocate list so that the klass is removed from the CLD::_klasses list | ||||||||||||
5702 | // at a safepoint. | ||||||||||||
5703 | if (_klass_to_deallocate != NULL__null) { | ||||||||||||
5704 | _loader_data->add_to_deallocate_list(_klass_to_deallocate); | ||||||||||||
5705 | } | ||||||||||||
5706 | } | ||||||||||||
5707 | |||||||||||||
5708 | void ClassFileParser::parse_stream(const ClassFileStream* const stream, | ||||||||||||
5709 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
5710 | |||||||||||||
5711 | assert(stream != NULL, "invariant")do { if (!(stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5711, "assert(" "stream != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); | ||||||||||||
5712 | assert(_class_name != NULL, "invariant")do { if (!(_class_name != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5712, "assert(" "_class_name != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5713 | |||||||||||||
5714 | // BEGIN STREAM PARSING | ||||||||||||
5715 | stream->guarantee_more(8, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // magic, major, minor | ||||||||||||
5716 | // Magic value | ||||||||||||
5717 | const u4 magic = stream->get_u4_fast(); | ||||||||||||
5718 | guarantee_property(magic == JAVA_CLASSFILE_MAGIC0xCAFEBABE, | ||||||||||||
5719 | "Incompatible magic value %u in class file %s", | ||||||||||||
5720 | magic, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5721 | |||||||||||||
5722 | // Version numbers | ||||||||||||
5723 | _minor_version = stream->get_u2_fast(); | ||||||||||||
5724 | _major_version = stream->get_u2_fast(); | ||||||||||||
5725 | |||||||||||||
5726 | // Check version numbers - we check this even with verifier off | ||||||||||||
5727 | verify_class_version(_major_version, _minor_version, _class_name, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5728 | |||||||||||||
5729 | stream->guarantee_more(3, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // length, first cp tag | ||||||||||||
5730 | u2 cp_size = stream->get_u2_fast(); | ||||||||||||
5731 | |||||||||||||
5732 | guarantee_property( | ||||||||||||
5733 | cp_size >= 1, "Illegal constant pool size %u in class file %s", | ||||||||||||
5734 | cp_size, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5735 | |||||||||||||
5736 | _orig_cp_size = cp_size; | ||||||||||||
5737 | if (is_hidden()) { // Add a slot for hidden class name. | ||||||||||||
5738 | cp_size++; | ||||||||||||
5739 | } | ||||||||||||
5740 | |||||||||||||
5741 | _cp = ConstantPool::allocate(_loader_data, | ||||||||||||
5742 | cp_size, | ||||||||||||
5743 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5744 | |||||||||||||
5745 | ConstantPool* const cp = _cp; | ||||||||||||
5746 | |||||||||||||
5747 | parse_constant_pool(stream, cp, _orig_cp_size, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5748 | |||||||||||||
5749 | assert(cp_size == (const u2)cp->length(), "invariant")do { if (!(cp_size == (const u2)cp->length())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5749, "assert(" "cp_size == (const u2)cp->length()" ") failed" , "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
5750 | |||||||||||||
5751 | // ACCESS FLAGS | ||||||||||||
5752 | stream->guarantee_more(8, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); // flags, this_class, super_class, infs_len | ||||||||||||
5753 | |||||||||||||
5754 | // Access flags | ||||||||||||
5755 | jint flags; | ||||||||||||
5756 | // JVM_ACC_MODULE is defined in JDK-9 and later. | ||||||||||||
5757 | if (_major_version >= JAVA_9_VERSION53) { | ||||||||||||
5758 | flags = stream->get_u2_fast() & (JVM_RECOGNIZED_CLASS_MODIFIERS(JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SUPER | JVM_ACC_INTERFACE | JVM_ACC_ABSTRACT | JVM_ACC_ANNOTATION | JVM_ACC_ENUM | JVM_ACC_SYNTHETIC ) | JVM_ACC_MODULE); | ||||||||||||
5759 | } else { | ||||||||||||
5760 | flags = stream->get_u2_fast() & JVM_RECOGNIZED_CLASS_MODIFIERS(JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SUPER | JVM_ACC_INTERFACE | JVM_ACC_ABSTRACT | JVM_ACC_ANNOTATION | JVM_ACC_ENUM | JVM_ACC_SYNTHETIC ); | ||||||||||||
5761 | } | ||||||||||||
5762 | |||||||||||||
5763 | if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION50) { | ||||||||||||
5764 | // Set abstract bit for old class files for backward compatibility | ||||||||||||
5765 | flags |= JVM_ACC_ABSTRACT; | ||||||||||||
5766 | } | ||||||||||||
5767 | |||||||||||||
5768 | verify_legal_class_modifiers(flags, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5769 | |||||||||||||
5770 | short bad_constant = class_bad_constant_seen(); | ||||||||||||
5771 | if (bad_constant != 0) { | ||||||||||||
5772 | // Do not throw CFE until after the access_flags are checked because if | ||||||||||||
5773 | // ACC_MODULE is set in the access flags, then NCDFE must be thrown, not CFE. | ||||||||||||
5774 | classfile_parse_error("Unknown constant tag %u in class file %s", bad_constant, THREAD__the_thread__); | ||||||||||||
5775 | return; | ||||||||||||
5776 | } | ||||||||||||
5777 | |||||||||||||
5778 | _access_flags.set_flags(flags); | ||||||||||||
5779 | |||||||||||||
5780 | // This class and superclass | ||||||||||||
5781 | _this_class_index = stream->get_u2_fast(); | ||||||||||||
5782 | check_property( | ||||||||||||
5783 | valid_cp_range(_this_class_index, cp_size) && | ||||||||||||
5784 | cp->tag_at(_this_class_index).is_unresolved_klass(), | ||||||||||||
5785 | "Invalid this class index %u in constant pool in class file %s", | ||||||||||||
5786 | _this_class_index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5787 | |||||||||||||
5788 | Symbol* const class_name_in_cp = cp->klass_name_at(_this_class_index); | ||||||||||||
5789 | assert(class_name_in_cp != NULL, "class_name can't be null")do { if (!(class_name_in_cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5789, "assert(" "class_name_in_cp != __null" ") failed", "class_name can't be null" ); ::breakpoint(); } } while (0); | ||||||||||||
5790 | |||||||||||||
5791 | // Don't need to check whether this class name is legal or not. | ||||||||||||
5792 | // It has been checked when constant pool is parsed. | ||||||||||||
5793 | // However, make sure it is not an array type. | ||||||||||||
5794 | if (_need_verify) { | ||||||||||||
5795 | guarantee_property(class_name_in_cp->char_at(0) != JVM_SIGNATURE_ARRAY, | ||||||||||||
5796 | "Bad class name in class file %s", | ||||||||||||
5797 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5798 | } | ||||||||||||
5799 | |||||||||||||
5800 | #ifdef ASSERT1 | ||||||||||||
5801 | // Basic sanity checks | ||||||||||||
5802 | if (_is_hidden) { | ||||||||||||
5803 | assert(_class_name != vmSymbols::unknown_class_name(), "hidden classes should have a special name")do { if (!(_class_name != vmSymbols::unknown_class_name())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5803, "assert(" "_class_name != vmSymbols::unknown_class_name()" ") failed", "hidden classes should have a special name"); :: breakpoint(); } } while (0); | ||||||||||||
5804 | } | ||||||||||||
5805 | #endif | ||||||||||||
5806 | |||||||||||||
5807 | // Update the _class_name as needed depending on whether this is a named, un-named, or hidden class. | ||||||||||||
5808 | |||||||||||||
5809 | if (_is_hidden) { | ||||||||||||
5810 | assert(_class_name != NULL, "Unexpected null _class_name")do { if (!(_class_name != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5810, "assert(" "_class_name != __null" ") failed", "Unexpected null _class_name" ); ::breakpoint(); } } while (0); | ||||||||||||
5811 | #ifdef ASSERT1 | ||||||||||||
5812 | if (_need_verify) { | ||||||||||||
5813 | verify_legal_class_name(_class_name, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5814 | } | ||||||||||||
5815 | #endif | ||||||||||||
5816 | |||||||||||||
5817 | } else { | ||||||||||||
5818 | // Check if name in class file matches given name | ||||||||||||
5819 | if (_class_name != class_name_in_cp) { | ||||||||||||
5820 | if (_class_name != vmSymbols::unknown_class_name()) { | ||||||||||||
5821 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
5822 | Exceptions::fthrow(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5822, | ||||||||||||
5823 | vmSymbols::java_lang_NoClassDefFoundError(), | ||||||||||||
5824 | "%s (wrong name: %s)", | ||||||||||||
5825 | class_name_in_cp->as_C_string(), | ||||||||||||
5826 | _class_name->as_C_string() | ||||||||||||
5827 | ); | ||||||||||||
5828 | return; | ||||||||||||
5829 | } else { | ||||||||||||
5830 | // The class name was not known by the caller so we set it from | ||||||||||||
5831 | // the value in the CP. | ||||||||||||
5832 | update_class_name(class_name_in_cp); | ||||||||||||
5833 | } | ||||||||||||
5834 | // else nothing to do: the expected class name matches what is in the CP | ||||||||||||
5835 | } | ||||||||||||
5836 | } | ||||||||||||
5837 | |||||||||||||
5838 | // Verification prevents us from creating names with dots in them, this | ||||||||||||
5839 | // asserts that that's the case. | ||||||||||||
5840 | assert(is_internal_format(_class_name), "external class name format used internally")do { if (!(is_internal_format(_class_name))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5840, "assert(" "is_internal_format(_class_name)" ") failed" , "external class name format used internally"); ::breakpoint (); } } while (0); | ||||||||||||
5841 | |||||||||||||
5842 | if (!is_internal()) { | ||||||||||||
5843 | LogTarget(Debug, class, preorder)LogTargetImpl<LogLevel::Debug, (LogTag::_class), (LogTag:: _preorder), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag:: __NO_TAG), (LogTag::__NO_TAG)> lt; | ||||||||||||
5844 | if (lt.is_enabled()){ | ||||||||||||
5845 | ResourceMark rm(THREAD__the_thread__); | ||||||||||||
5846 | LogStream ls(lt); | ||||||||||||
5847 | ls.print("%s", _class_name->as_klass_external_name()); | ||||||||||||
5848 | if (stream->source() != NULL__null) { | ||||||||||||
5849 | ls.print(" source: %s", stream->source()); | ||||||||||||
5850 | } | ||||||||||||
5851 | ls.cr(); | ||||||||||||
5852 | } | ||||||||||||
5853 | } | ||||||||||||
5854 | |||||||||||||
5855 | // SUPERKLASS | ||||||||||||
5856 | _super_class_index = stream->get_u2_fast(); | ||||||||||||
5857 | _super_klass = parse_super_class(cp, | ||||||||||||
5858 | _super_class_index, | ||||||||||||
5859 | _need_verify, | ||||||||||||
5860 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5861 | |||||||||||||
5862 | // Interfaces | ||||||||||||
5863 | _itfs_len = stream->get_u2_fast(); | ||||||||||||
5864 | parse_interfaces(stream, | ||||||||||||
5865 | _itfs_len, | ||||||||||||
5866 | cp, | ||||||||||||
5867 | &_has_nonstatic_concrete_methods, | ||||||||||||
5868 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5869 | |||||||||||||
5870 | assert(_local_interfaces != NULL, "invariant")do { if (!(_local_interfaces != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5870, "assert(" "_local_interfaces != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5871 | |||||||||||||
5872 | // Fields (offsets are filled in later) | ||||||||||||
5873 | _fac = new FieldAllocationCount(); | ||||||||||||
5874 | parse_fields(stream, | ||||||||||||
5875 | _access_flags.is_interface(), | ||||||||||||
5876 | _fac, | ||||||||||||
5877 | cp, | ||||||||||||
5878 | cp_size, | ||||||||||||
5879 | &_java_fields_count, | ||||||||||||
5880 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5881 | |||||||||||||
5882 | assert(_fields != NULL, "invariant")do { if (!(_fields != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5882, "assert(" "_fields != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5883 | |||||||||||||
5884 | // Methods | ||||||||||||
5885 | AccessFlags promoted_flags; | ||||||||||||
5886 | parse_methods(stream, | ||||||||||||
5887 | _access_flags.is_interface(), | ||||||||||||
5888 | &promoted_flags, | ||||||||||||
5889 | &_has_final_method, | ||||||||||||
5890 | &_declares_nonstatic_concrete_methods, | ||||||||||||
5891 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5892 | |||||||||||||
5893 | assert(_methods != NULL, "invariant")do { if (!(_methods != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5893, "assert(" "_methods != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5894 | |||||||||||||
5895 | // promote flags from parse_methods() to the klass' flags | ||||||||||||
5896 | _access_flags.add_promoted_flags(promoted_flags.as_int()); | ||||||||||||
5897 | |||||||||||||
5898 | if (_declares_nonstatic_concrete_methods) { | ||||||||||||
5899 | _has_nonstatic_concrete_methods = true; | ||||||||||||
5900 | } | ||||||||||||
5901 | |||||||||||||
5902 | // Additional attributes/annotations | ||||||||||||
5903 | _parsed_annotations = new ClassAnnotationCollector(); | ||||||||||||
5904 | parse_classfile_attributes(stream, cp, _parsed_annotations, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5905 | |||||||||||||
5906 | assert(_inner_classes != NULL, "invariant")do { if (!(_inner_classes != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5906, "assert(" "_inner_classes != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5907 | |||||||||||||
5908 | // Finalize the Annotations metadata object, | ||||||||||||
5909 | // now that all annotation arrays have been created. | ||||||||||||
5910 | create_combined_annotations(CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5911 | |||||||||||||
5912 | // Make sure this is the end of class file stream | ||||||||||||
5913 | guarantee_property(stream->at_eos(), | ||||||||||||
5914 | "Extra bytes at the end of class file %s", | ||||||||||||
5915 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5916 | |||||||||||||
5917 | // all bytes in stream read and parsed | ||||||||||||
5918 | } | ||||||||||||
5919 | |||||||||||||
5920 | void ClassFileParser::mangle_hidden_class_name(InstanceKlass* const ik) { | ||||||||||||
5921 | ResourceMark rm; | ||||||||||||
5922 | // Construct hidden name from _class_name, "+", and &ik. Note that we can't | ||||||||||||
5923 | // use a '/' because that confuses finding the class's package. Also, can't | ||||||||||||
5924 | // use an illegal char such as ';' because that causes serialization issues | ||||||||||||
5925 | // and issues with hidden classes that create their own hidden classes. | ||||||||||||
5926 | char addr_buf[20]; | ||||||||||||
5927 | if (DumpSharedSpaces) { | ||||||||||||
5928 | // We want stable names for the archived hidden classes (only for static | ||||||||||||
5929 | // archive for now). Spaces under default_SharedBaseAddress() will be | ||||||||||||
5930 | // occupied by the archive at run time, so we know that no dynamically | ||||||||||||
5931 | // loaded InstanceKlass will be placed under there. | ||||||||||||
5932 | static volatile size_t counter = 0; | ||||||||||||
5933 | Atomic::cmpxchg(&counter, (size_t)0, Arguments::default_SharedBaseAddress()); // initialize it | ||||||||||||
5934 | size_t new_id = Atomic::add(&counter, (size_t)1); | ||||||||||||
5935 | jio_snprintf(addr_buf, 20, SIZE_FORMAT_HEX"0x%" "l" "x", new_id); | ||||||||||||
5936 | } else { | ||||||||||||
5937 | jio_snprintf(addr_buf, 20, INTPTR_FORMAT"0x%016" "l" "x", p2i(ik)); | ||||||||||||
5938 | } | ||||||||||||
5939 | size_t new_name_len = _class_name->utf8_length() + 2 + strlen(addr_buf); | ||||||||||||
5940 | char* new_name = NEW_RESOURCE_ARRAY(char, new_name_len)(char*) resource_allocate_bytes((new_name_len) * sizeof(char) ); | ||||||||||||
5941 | jio_snprintf(new_name, new_name_len, "%s+%s", | ||||||||||||
5942 | _class_name->as_C_string(), addr_buf); | ||||||||||||
5943 | update_class_name(SymbolTable::new_symbol(new_name)); | ||||||||||||
5944 | |||||||||||||
5945 | // Add a Utf8 entry containing the hidden name. | ||||||||||||
5946 | assert(_class_name != NULL, "Unexpected null _class_name")do { if (!(_class_name != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5946, "assert(" "_class_name != __null" ") failed", "Unexpected null _class_name" ); ::breakpoint(); } } while (0); | ||||||||||||
5947 | int hidden_index = _orig_cp_size; // this is an extra slot we added | ||||||||||||
5948 | _cp->symbol_at_put(hidden_index, _class_name); | ||||||||||||
5949 | |||||||||||||
5950 | // Update this_class_index's slot in the constant pool with the new Utf8 entry. | ||||||||||||
5951 | // We have to update the resolved_klass_index and the name_index together | ||||||||||||
5952 | // so extract the existing resolved_klass_index first. | ||||||||||||
5953 | CPKlassSlot cp_klass_slot = _cp->klass_slot_at(_this_class_index); | ||||||||||||
5954 | int resolved_klass_index = cp_klass_slot.resolved_klass_index(); | ||||||||||||
5955 | _cp->unresolved_klass_at_put(_this_class_index, hidden_index, resolved_klass_index); | ||||||||||||
5956 | assert(_cp->klass_slot_at(_this_class_index).name_index() == _orig_cp_size,do { if (!(_cp->klass_slot_at(_this_class_index).name_index () == _orig_cp_size)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5957, "assert(" "_cp->klass_slot_at(_this_class_index).name_index() == _orig_cp_size" ") failed", "Bad name_index"); ::breakpoint(); } } while (0) | ||||||||||||
5957 | "Bad name_index")do { if (!(_cp->klass_slot_at(_this_class_index).name_index () == _orig_cp_size)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5957, "assert(" "_cp->klass_slot_at(_this_class_index).name_index() == _orig_cp_size" ") failed", "Bad name_index"); ::breakpoint(); } } while (0); | ||||||||||||
5958 | } | ||||||||||||
5959 | |||||||||||||
5960 | void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const stream, | ||||||||||||
5961 | ConstantPool* cp, | ||||||||||||
5962 | TRAPSJavaThread* __the_thread__) { | ||||||||||||
5963 | assert(stream != NULL, "invariant")do { if (!(stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5963, "assert(" "stream != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); | ||||||||||||
5964 | assert(stream->at_eos(), "invariant")do { if (!(stream->at_eos())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5964, "assert(" "stream->at_eos()" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5965 | assert(cp != NULL, "invariant")do { if (!(cp != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5965, "assert(" "cp != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
5966 | assert(_loader_data != NULL, "invariant")do { if (!(_loader_data != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 5966, "assert(" "_loader_data != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
5967 | |||||||||||||
5968 | if (_class_name == vmSymbols::java_lang_Object()) { | ||||||||||||
5969 | check_property(_local_interfaces == Universe::the_empty_instance_klass_array(), | ||||||||||||
5970 | "java.lang.Object cannot implement an interface in class file %s", | ||||||||||||
5971 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5972 | } | ||||||||||||
5973 | // We check super class after class file is parsed and format is checked | ||||||||||||
5974 | if (_super_class_index > 0 && NULL__null == _super_klass) { | ||||||||||||
5975 | Symbol* const super_class_name = cp->klass_name_at(_super_class_index); | ||||||||||||
5976 | if (_access_flags.is_interface()) { | ||||||||||||
5977 | // Before attempting to resolve the superclass, check for class format | ||||||||||||
5978 | // errors not checked yet. | ||||||||||||
5979 | guarantee_property(super_class_name == vmSymbols::java_lang_Object(), | ||||||||||||
5980 | "Interfaces must have java.lang.Object as superclass in class file %s", | ||||||||||||
5981 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5982 | } | ||||||||||||
5983 | Handle loader(THREAD__the_thread__, _loader_data->class_loader()); | ||||||||||||
5984 | _super_klass = (const InstanceKlass*) | ||||||||||||
5985 | SystemDictionary::resolve_super_or_fail(_class_name, | ||||||||||||
5986 | super_class_name, | ||||||||||||
5987 | loader, | ||||||||||||
5988 | _protection_domain, | ||||||||||||
5989 | true, | ||||||||||||
5990 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
5991 | } | ||||||||||||
5992 | |||||||||||||
5993 | if (_super_klass != NULL__null) { | ||||||||||||
5994 | if (_super_klass->has_nonstatic_concrete_methods()) { | ||||||||||||
5995 | _has_nonstatic_concrete_methods = true; | ||||||||||||
5996 | } | ||||||||||||
5997 | |||||||||||||
5998 | if (_super_klass->is_interface()) { | ||||||||||||
5999 | classfile_icce_error("class %s has interface %s as super class", _super_klass, THREAD__the_thread__); | ||||||||||||
6000 | return; | ||||||||||||
6001 | } | ||||||||||||
6002 | } | ||||||||||||
6003 | |||||||||||||
6004 | // Compute the transitive list of all unique interfaces implemented by this class | ||||||||||||
6005 | _transitive_interfaces = | ||||||||||||
6006 | compute_transitive_interfaces(_super_klass, | ||||||||||||
6007 | _local_interfaces, | ||||||||||||
6008 | _loader_data, | ||||||||||||
6009 | CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
6010 | |||||||||||||
6011 | assert(_transitive_interfaces != NULL, "invariant")do { if (!(_transitive_interfaces != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 6011, "assert(" "_transitive_interfaces != __null" ") failed" , "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
6012 | |||||||||||||
6013 | // sort methods | ||||||||||||
6014 | _method_ordering = sort_methods(_methods); | ||||||||||||
6015 | |||||||||||||
6016 | _all_mirandas = new GrowableArray<Method*>(20); | ||||||||||||
6017 | |||||||||||||
6018 | Handle loader(THREAD__the_thread__, _loader_data->class_loader()); | ||||||||||||
6019 | klassVtable::compute_vtable_size_and_num_mirandas(&_vtable_size, | ||||||||||||
6020 | &_num_miranda_methods, | ||||||||||||
6021 | _all_mirandas, | ||||||||||||
6022 | _super_klass, | ||||||||||||
6023 | _methods, | ||||||||||||
6024 | _access_flags, | ||||||||||||
6025 | _major_version, | ||||||||||||
6026 | loader, | ||||||||||||
6027 | _class_name, | ||||||||||||
6028 | _local_interfaces); | ||||||||||||
6029 | |||||||||||||
6030 | // Size of Java itable (in words) | ||||||||||||
6031 | _itable_size = _access_flags.is_interface() ? 0 : | ||||||||||||
6032 | klassItable::compute_itable_size(_transitive_interfaces); | ||||||||||||
6033 | |||||||||||||
6034 | assert(_fac != NULL, "invariant")do { if (!(_fac != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 6034, "assert(" "_fac != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); | ||||||||||||
6035 | assert(_parsed_annotations != NULL, "invariant")do { if (!(_parsed_annotations != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 6035, "assert(" "_parsed_annotations != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); | ||||||||||||
6036 | |||||||||||||
6037 | _field_info = new FieldLayoutInfo(); | ||||||||||||
6038 | FieldLayoutBuilder lb(class_name(), super_klass(), _cp, _fields, | ||||||||||||
6039 | _parsed_annotations->is_contended(), _field_info); | ||||||||||||
6040 | lb.build_layout(); | ||||||||||||
6041 | |||||||||||||
6042 | // Compute reference typ | ||||||||||||
6043 | _rt = (NULL__null ==_super_klass) ? REF_NONE : _super_klass->reference_type(); | ||||||||||||
6044 | |||||||||||||
6045 | } | ||||||||||||
6046 | |||||||||||||
6047 | void ClassFileParser::set_klass(InstanceKlass* klass) { | ||||||||||||
6048 | |||||||||||||
6049 | #ifdef ASSERT1 | ||||||||||||
6050 | if (klass != NULL__null) { | ||||||||||||
6051 | assert(NULL == _klass, "leaking?")do { if (!(__null == _klass)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 6051, "assert(" "__null == _klass" ") failed", "leaking?"); ::breakpoint(); } } while (0); | ||||||||||||
6052 | } | ||||||||||||
6053 | #endif | ||||||||||||
6054 | |||||||||||||
6055 | _klass = klass; | ||||||||||||
6056 | } | ||||||||||||
6057 | |||||||||||||
6058 | void ClassFileParser::set_klass_to_deallocate(InstanceKlass* klass) { | ||||||||||||
6059 | |||||||||||||
6060 | #ifdef ASSERT1 | ||||||||||||
6061 | if (klass != NULL__null) { | ||||||||||||
6062 | assert(NULL == _klass_to_deallocate, "leaking?")do { if (!(__null == _klass_to_deallocate)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 6062, "assert(" "__null == _klass_to_deallocate" ") failed" , "leaking?"); ::breakpoint(); } } while (0); | ||||||||||||
6063 | } | ||||||||||||
6064 | #endif | ||||||||||||
6065 | |||||||||||||
6066 | _klass_to_deallocate = klass; | ||||||||||||
6067 | } | ||||||||||||
6068 | |||||||||||||
6069 | // Caller responsible for ResourceMark | ||||||||||||
6070 | // clone stream with rewound position | ||||||||||||
6071 | const ClassFileStream* ClassFileParser::clone_stream() const { | ||||||||||||
6072 | assert(_stream != NULL, "invariant")do { if (!(_stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/classFileParser.cpp" , 6072, "assert(" "_stream != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); | ||||||||||||
6073 | |||||||||||||
6074 | return _stream->clone(); | ||||||||||||
6075 | } | ||||||||||||
6076 | // ---------------------------------------------------------------------------- | ||||||||||||
6077 | // debugging | ||||||||||||
6078 | |||||||||||||
6079 | #ifdef ASSERT1 | ||||||||||||
6080 | |||||||||||||
6081 | // return true if class_name contains no '.' (internal format is '/') | ||||||||||||
6082 | bool ClassFileParser::is_internal_format(Symbol* class_name) { | ||||||||||||
6083 | if (class_name != NULL__null) { | ||||||||||||
6084 | ResourceMark rm; | ||||||||||||
6085 | char* name = class_name->as_C_string(); | ||||||||||||
6086 | return strchr(name, JVM_SIGNATURE_DOT) == NULL__null; | ||||||||||||
6087 | } else { | ||||||||||||
6088 | return true; | ||||||||||||
6089 | } | ||||||||||||
6090 | } | ||||||||||||
6091 | |||||||||||||
6092 | #endif |
1 | /* |
2 | * Copyright (c) 1998, 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 | #ifndef SHARE_UTILITIES_EXCEPTIONS_HPP |
26 | #define SHARE_UTILITIES_EXCEPTIONS_HPP |
27 | |
28 | #include "memory/allocation.hpp" |
29 | #include "oops/oopsHierarchy.hpp" |
30 | #include "utilities/ostream.hpp" |
31 | #include "utilities/sizes.hpp" |
32 | |
33 | // This file provides the basic support for exception handling in the VM. |
34 | // Note: We do not use C++ exceptions to avoid compiler dependencies and |
35 | // unpredictable performance. |
36 | // |
37 | // Scheme: Exceptions are stored with the thread. There is never more |
38 | // than one pending exception per thread. All functions that can throw |
39 | // an exception carry a THREAD argument (usually the last argument and |
40 | // declared with the TRAPS macro). Throwing an exception means setting |
41 | // a pending exception in the thread. Upon return from a function that |
42 | // can throw an exception, we must check if an exception is pending. |
43 | // The CHECK macros do this in a convenient way. Carrying around the |
44 | // thread provides also convenient access to it (e.g. for Handle |
45 | // creation, w/o the need for recomputation). |
46 | |
47 | |
48 | |
49 | // Forward declarations to be independent of the include structure. |
50 | |
51 | class JavaThread; |
52 | class Handle; |
53 | class Symbol; |
54 | class JavaCallArguments; |
55 | class methodHandle; |
56 | |
57 | // The ThreadShadow class is a helper class to access the _pending_exception |
58 | // field of the Thread class w/o having access to the Thread's interface (for |
59 | // include hierachy reasons). |
60 | |
61 | class ThreadShadow: public CHeapObj<mtThread> { |
62 | friend class VMStructs; |
63 | friend class JVMCIVMStructs; |
64 | |
65 | protected: |
66 | oop _pending_exception; // Thread has gc actions. |
67 | const char* _exception_file; // file information for exception (debugging only) |
68 | int _exception_line; // line information for exception (debugging only) |
69 | friend void check_ThreadShadow(); // checks _pending_exception offset |
70 | |
71 | // The following virtual exists only to force creation of a vtable. |
72 | // We need ThreadShadow to have a vtable, even in product builds, |
73 | // so that its layout will start at an offset of zero relative to Thread. |
74 | // Some C++ compilers are so "clever" that they put the ThreadShadow |
75 | // base class at offset 4 in Thread (after Thread's vtable), if they |
76 | // notice that Thread has a vtable but ThreadShadow does not. |
77 | virtual void unused_initial_virtual() { } |
78 | |
79 | public: |
80 | oop pending_exception() const { return _pending_exception; } |
81 | bool has_pending_exception() const { return _pending_exception != NULL__null; } |
82 | const char* exception_file() const { return _exception_file; } |
83 | int exception_line() const { return _exception_line; } |
84 | |
85 | // Code generation support |
86 | static ByteSize pending_exception_offset() { return byte_offset_of(ThreadShadow, _pending_exception)in_ByteSize((int)(size_t)((intx)&(((ThreadShadow*)16)-> _pending_exception) - 16)); } |
87 | |
88 | // use THROW whenever possible! |
89 | void set_pending_exception(oop exception, const char* file, int line); |
90 | |
91 | // use CLEAR_PENDING_EXCEPTION whenever possible! |
92 | void clear_pending_exception(); |
93 | |
94 | // use CLEAR_PENDING_NONASYNC_EXCEPTION to clear probable nonasync exception. |
95 | void clear_pending_nonasync_exception(); |
96 | |
97 | ThreadShadow() : _pending_exception(NULL__null), |
98 | _exception_file(NULL__null), _exception_line(0) {} |
99 | }; |
100 | |
101 | |
102 | // Exceptions is a helper class that encapsulates all operations |
103 | // that require access to the thread interface and which are |
104 | // relatively rare. The Exceptions operations should only be |
105 | // used directly if the macros below are insufficient. |
106 | |
107 | class Exceptions { |
108 | static bool special_exception(JavaThread* thread, const char* file, int line, Handle exception); |
109 | static bool special_exception(JavaThread* thread, const char* file, int line, Symbol* name, const char* message); |
110 | |
111 | // Count out of memory errors that are interesting in error diagnosis |
112 | static volatile int _out_of_memory_error_java_heap_errors; |
113 | static volatile int _out_of_memory_error_metaspace_errors; |
114 | static volatile int _out_of_memory_error_class_metaspace_errors; |
115 | |
116 | // Count linkage errors |
117 | static volatile int _linkage_errors; |
118 | public: |
119 | // this enum is defined to indicate whether it is safe to |
120 | // ignore the encoding scheme of the original message string. |
121 | typedef enum { |
122 | safe_to_utf8 = 0, |
123 | unsafe_to_utf8 = 1 |
124 | } ExceptionMsgToUtf8Mode; |
125 | // Throw exceptions: w/o message, w/ message & with formatted message. |
126 | static void _throw_oop(JavaThread* thread, const char* file, int line, oop exception); |
127 | static void _throw(JavaThread* thread, const char* file, int line, Handle exception, const char* msg = NULL__null); |
128 | |
129 | static void _throw_msg(JavaThread* thread, const char* file, int line, Symbol* name, const char* message); |
130 | static void _throw_msg(JavaThread* thread, const char* file, int line, Symbol* name, const char* message, |
131 | Handle loader, Handle protection_domain); |
132 | |
133 | static void _throw_msg_cause(JavaThread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause); |
134 | static void _throw_msg_cause(JavaThread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause, |
135 | Handle h_loader, Handle h_protection_domain); |
136 | |
137 | static void _throw_cause(JavaThread* thread, const char* file, int line, Symbol* name, Handle h_cause); |
138 | static void _throw_cause(JavaThread* thread, const char* file, int line, Symbol* name, Handle h_cause, |
139 | Handle h_loader, Handle h_protection_domain); |
140 | |
141 | static void _throw_args(JavaThread* thread, const char* file, int line, |
142 | Symbol* name, Symbol* signature, |
143 | JavaCallArguments* args); |
144 | |
145 | // There is no THROW... macro for this method. Caller should remember |
146 | // to do a return after calling it. |
147 | static void fthrow(JavaThread* thread, const char* file, int line, Symbol* name, |
148 | const char* format, ...) ATTRIBUTE_PRINTF(5, 6)__attribute__((format(printf, 5, 6))); |
149 | |
150 | // Create and initialize a new exception |
151 | static Handle new_exception(JavaThread* thread, Symbol* name, |
152 | Symbol* signature, JavaCallArguments* args, |
153 | Handle loader, Handle protection_domain); |
154 | |
155 | static Handle new_exception(JavaThread* thread, Symbol* name, |
156 | Symbol* signature, JavaCallArguments* args, |
157 | Handle cause, |
158 | Handle loader, Handle protection_domain); |
159 | |
160 | static Handle new_exception(JavaThread* thread, Symbol* name, |
161 | Handle cause, |
162 | Handle loader, Handle protection_domain, |
163 | ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8); |
164 | |
165 | static Handle new_exception(JavaThread* thread, Symbol* name, |
166 | const char* message, Handle cause, |
167 | Handle loader, Handle protection_domain, |
168 | ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8); |
169 | |
170 | static Handle new_exception(JavaThread* thread, Symbol* name, |
171 | const char* message, |
172 | ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8); |
173 | |
174 | static void throw_stack_overflow_exception(JavaThread* thread, const char* file, int line, const methodHandle& method); |
175 | |
176 | static void throw_unsafe_access_internal_error(JavaThread* thread, const char* file, int line, const char* message); |
177 | |
178 | static void wrap_dynamic_exception(bool is_indy, JavaThread* thread); |
179 | |
180 | // Exception counting for error files of interesting exceptions that may have |
181 | // caused a problem for the jvm |
182 | static volatile int _stack_overflow_errors; |
183 | |
184 | static bool has_exception_counts(); |
185 | static void count_out_of_memory_exceptions(Handle exception); |
186 | static void print_exception_counts_on_error(outputStream* st); |
187 | |
188 | // for AbortVMOnException flag |
189 | static void debug_check_abort(Handle exception, const char* message = NULL__null); |
190 | static void debug_check_abort_helper(Handle exception, const char* message = NULL__null); |
191 | static void debug_check_abort(const char *value_string, const char* message = NULL__null); |
192 | |
193 | // for logging exceptions |
194 | static void log_exception(Handle exception, const char* message); |
195 | }; |
196 | |
197 | |
198 | // The THREAD & TRAPS macros facilitate the declaration of functions that throw exceptions. |
199 | // Convention: Use the TRAPS macro as the last argument of such a function; e.g.: |
200 | // |
201 | // int this_function_may_trap(int x, float y, TRAPS) |
202 | |
203 | #define THREAD__the_thread__ __the_thread__ |
204 | #define TRAPSJavaThread* __the_thread__ JavaThread* THREAD__the_thread__ |
205 | |
206 | |
207 | // The CHECK... macros should be used to pass along a THREAD reference and to check for pending |
208 | // exceptions. In special situations it is necessary to handle pending exceptions explicitly, |
209 | // in these cases the PENDING_EXCEPTION helper macros should be used. |
210 | // |
211 | // Macro naming conventions: Macros that end with _ require a result value to be returned. They |
212 | // are for functions with non-void result type. The result value is usually ignored because of |
213 | // the exception and is only needed for syntactic correctness. The _0 ending is a shortcut for |
214 | // _(0) since this is a frequent case. Example: |
215 | // |
216 | // int result = this_function_may_trap(x_arg, y_arg, CHECK_0); |
217 | // |
218 | // CAUTION: make sure that the function call using a CHECK macro is not the only statement of a |
219 | // conditional branch w/o enclosing {} braces, since the CHECK macros expand into several state- |
220 | // ments! Also make sure it is not used on a function call that is part of a return statement! |
221 | |
222 | #define PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->pending_exception()) (((ThreadShadow*)THREAD__the_thread__)->pending_exception()) |
223 | #define HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception()) (((ThreadShadow*)THREAD__the_thread__)->has_pending_exception()) |
224 | #define CLEAR_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_exception( )) (((ThreadShadow*)THREAD__the_thread__)->clear_pending_exception()) |
225 | |
226 | #define CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0 THREAD__the_thread__); if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) return ; (void)(0 |
227 | #define CHECK_(result)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return result; (void)(0 THREAD__the_thread__); if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) return result; (void)(0 |
228 | #define CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0 CHECK_(0)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0 |
229 | #define CHECK_NH__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return Handle(); (void)(0 CHECK_(Handle())__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return Handle(); (void)(0 |
230 | #define CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0 CHECK_(NULL)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0 |
231 | #define CHECK_false__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return false; (void)(0 CHECK_(false)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return false; (void)(0 |
232 | #define CHECK_JNI_ERR__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return (-1); (void)(0 CHECK_(JNI_ERR)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return (-1); (void)(0 |
233 | |
234 | // CAUTION: These macros clears all exceptions including async exceptions, use it with caution. |
235 | #define CHECK_AND_CLEAR__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return; } (void)(0 THREAD__the_thread__); if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) { CLEAR_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_exception( )); return; } (void)(0 |
236 | #define CHECK_AND_CLEAR_(result)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return result; } (void)(0 THREAD__the_thread__); if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) { CLEAR_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_exception( )); return result; } (void)(0 |
237 | #define CHECK_AND_CLEAR_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return 0; } (void)(0 CHECK_AND_CLEAR_(0)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return 0; } (void)(0 |
238 | #define CHECK_AND_CLEAR_NH__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return Handle(); } (void)(0 CHECK_AND_CLEAR_(Handle())__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return Handle(); } (void)(0 |
239 | #define CHECK_AND_CLEAR_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return __null; } (void)(0 CHECK_AND_CLEAR_(NULL)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return __null; } (void)(0 |
240 | #define CHECK_AND_CLEAR_false__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return false; } (void)(0 CHECK_AND_CLEAR_(false)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return false; } (void)(0 |
241 | |
242 | // CAUTION: These macros clears all exceptions except probable async exceptions j.l.InternalError and j.l.ThreadDeath. |
243 | // So use it with caution. |
244 | #define CLEAR_PENDING_NONASYNC_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()) (((ThreadShadow*)THREAD__the_thread__)->clear_pending_nonasync_exception()) |
245 | #define CHECK_AND_CLEAR_NONASYNC__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return; } (void)(0 THREAD__the_thread__); if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) { CLEAR_PENDING_NONASYNC_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return; } (void)(0 |
246 | #define CHECK_AND_CLEAR_NONASYNC_(result)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return result; } (void)(0 THREAD__the_thread__); if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) { CLEAR_PENDING_NONASYNC_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return result; } (void)(0 |
247 | #define CHECK_AND_CLEAR_NONASYNC_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return 0; } (void)(0 CHECK_AND_CLEAR_NONASYNC_(0)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return 0; } (void)(0 |
248 | #define CHECK_AND_CLEAR_NONASYNC_NH__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return Handle(); } (void)(0 CHECK_AND_CLEAR_NONASYNC_(Handle())__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return Handle(); } (void)(0 |
249 | #define CHECK_AND_CLEAR_NONASYNC_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return __null; } (void)(0 CHECK_AND_CLEAR_NONASYNC_(NULL)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return __null; } (void)(0 |
250 | #define CHECK_AND_CLEAR_NONASYNC_false__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return false; } (void)(0 CHECK_AND_CLEAR_NONASYNC_(false)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return false; } (void)(0 |
251 | |
252 | // The THROW... macros should be used to throw an exception. They require a THREAD variable to be |
253 | // visible within the scope containing the THROW. Usually this is achieved by declaring the function |
254 | // with a TRAPS argument. |
255 | |
256 | #define THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 256 THREAD__the_thread__, __FILE__"/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp", __LINE__256 |
257 | |
258 | #define THROW_OOP(e){ Exceptions::_throw_oop(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 258, e); return; } \ |
259 | { Exceptions::_throw_oop(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 259, e); return; } |
260 | |
261 | #define THROW_HANDLE(e){ Exceptions::_throw(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 261, e); return; } \ |
262 | { Exceptions::_throw(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 262, e); return; } |
263 | |
264 | #define THROW(name){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 264, name, __null); return; } \ |
265 | { Exceptions::_throw_msg(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 265, name, NULL__null); return; } |
266 | |
267 | #define THROW_MSG(name, message){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 267, name, message); return; } \ |
268 | { Exceptions::_throw_msg(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 268, name, message); return; } |
269 | |
270 | #define THROW_CAUSE(name, cause){ Exceptions::_throw_cause(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 270, name, cause); return; } \ |
271 | { Exceptions::_throw_cause(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 271, name, cause); return; } |
272 | |
273 | #define THROW_MSG_LOADER(name, message, loader, protection_domain){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 273, name, message, loader, protection_domain); return; } \ |
274 | { Exceptions::_throw_msg(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 274, name, message, loader, protection_domain); return; } |
275 | |
276 | #define THROW_ARG(name, signature, args){ Exceptions::_throw_args(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 276, name, signature, args); return; } \ |
277 | { Exceptions::_throw_args(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 277, name, signature, args); return; } |
278 | |
279 | #define THROW_OOP_(e, result){ Exceptions::_throw_oop(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 279, e); return result; } \ |
280 | { Exceptions::_throw_oop(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 280, e); return result; } |
281 | |
282 | #define THROW_HANDLE_(e, result){ Exceptions::_throw(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 282, e); return result; } \ |
283 | { Exceptions::_throw(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 283, e); return result; } |
284 | |
285 | #define THROW_(name, result){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 285, name, __null); return result; } \ |
286 | { Exceptions::_throw_msg(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 286, name, NULL__null); return result; } |
287 | |
288 | #define THROW_MSG_(name, message, result){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 288, name, message); return result; } \ |
289 | { Exceptions::_throw_msg(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 289, name, message); return result; } |
290 | |
291 | #define THROW_MSG_LOADER_(name, message, loader, protection_domain, result){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 291, name, message, loader, protection_domain); return result ; } \ |
292 | { Exceptions::_throw_msg(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 292, name, message, loader, protection_domain); return result; } |
293 | |
294 | #define THROW_ARG_(name, signature, args, result){ Exceptions::_throw_args(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 294, name, signature, args); return result; } \ |
295 | { Exceptions::_throw_args(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 295, name, signature, args); return result; } |
296 | |
297 | #define THROW_MSG_CAUSE(name, message, cause){ Exceptions::_throw_msg_cause(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 297, name, message, cause); return; } \ |
298 | { Exceptions::_throw_msg_cause(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 298, name, message, cause); return; } |
299 | |
300 | #define THROW_MSG_CAUSE_(name, message, cause, result){ Exceptions::_throw_msg_cause(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 300, name, message, cause); return result; } \ |
301 | { Exceptions::_throw_msg_cause(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 301, name, message, cause); return result; } |
302 | |
303 | |
304 | #define THROW_OOP_0(e){ Exceptions::_throw_oop(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 304, e); return 0; } THROW_OOP_(e, 0){ Exceptions::_throw_oop(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 304, e); return 0; } |
305 | #define THROW_HANDLE_0(e){ Exceptions::_throw(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 305, e); return 0; } THROW_HANDLE_(e, 0){ Exceptions::_throw(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 305, e); return 0; } |
306 | #define THROW_0(name){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 306, name, __null); return 0; } THROW_(name, 0){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 306, name, __null); return 0; } |
307 | #define THROW_MSG_0(name, message){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 307, name, message); return 0; } THROW_MSG_(name, message, 0){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 307, name, message); return 0; } |
308 | #define THROW_WRAPPED_0(name, oop_to_wrap)THROW_WRAPPED_(name, oop_to_wrap, 0) THROW_WRAPPED_(name, oop_to_wrap, 0) |
309 | #define THROW_ARG_0(name, signature, arg){ Exceptions::_throw_args(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 309, name, signature, arg); return 0; } THROW_ARG_(name, signature, arg, 0){ Exceptions::_throw_args(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 309, name, signature, arg); return 0; } |
310 | #define THROW_MSG_CAUSE_0(name, message, cause){ Exceptions::_throw_msg_cause(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 310, name, message, cause); return 0; } THROW_MSG_CAUSE_(name, message, cause, 0){ Exceptions::_throw_msg_cause(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 310, name, message, cause); return 0; } |
311 | #define THROW_MSG_CAUSE_NULL(name, message, cause){ Exceptions::_throw_msg_cause(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 311, name, message, cause); return __null; } THROW_MSG_CAUSE_(name, message, cause, NULL){ Exceptions::_throw_msg_cause(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 311, name, message, cause); return __null; } |
312 | |
313 | #define THROW_NULL(name){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 313, name, __null); return __null; } THROW_(name, NULL){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 313, name, __null); return __null; } |
314 | #define THROW_MSG_NULL(name, message){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 314, name, message); return __null; } THROW_MSG_(name, message, NULL){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 314, name, message); return __null; } |
315 | |
316 | // The CATCH macro checks that no exception has been thrown by a function; it is used at |
317 | // call sites about which is statically known that the callee cannot throw an exception |
318 | // even though it is declared with TRAPS. |
319 | |
320 | #define CATCH__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { oop ex = (((ThreadShadow*)__the_thread__)->pending_exception ()); (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); ex->print(); do { if (!(false)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 320, "assert(" "false" ") failed", "CATCH"); ::breakpoint() ; } } while (0); } (void)(0 \ |
321 | THREAD__the_thread__); if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) { \ |
322 | oop ex = PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->pending_exception()); \ |
323 | CLEAR_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_exception( )); \ |
324 | DEBUG_ONLY(ex->print();)ex->print(); \ |
325 | assert(false, "CATCH")do { if (!(false)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 325, "assert(" "false" ") failed", "CATCH"); ::breakpoint() ; } } while (0); \ |
326 | } (void)(0 |
327 | |
328 | // ExceptionMark is a stack-allocated helper class for local exception handling. |
329 | // It is used with the EXCEPTION_MARK macro. |
330 | |
331 | class ExceptionMark { |
332 | private: |
333 | JavaThread* _thread; |
334 | inline void check_no_pending_exception(); |
335 | |
336 | public: |
337 | ExceptionMark(); |
338 | ExceptionMark(JavaThread* thread); |
339 | ~ExceptionMark(); |
340 | |
341 | JavaThread* thread() { |
342 | return _thread; |
343 | } |
344 | }; |
345 | |
346 | // Use an EXCEPTION_MARK for 'local' exceptions. EXCEPTION_MARK makes sure that no |
347 | // pending exception exists upon entering its scope and tests that no pending exception |
348 | // exists when leaving the scope. |
349 | |
350 | // See also preserveException.hpp for PreserveExceptionMark |
351 | // which preserves pre-existing exceptions and does not allow new |
352 | // exceptions. |
353 | |
354 | #define EXCEPTION_MARKExceptionMark __em; JavaThread* __the_thread__ = __em.thread( ); ExceptionMark __em; JavaThread* THREAD__the_thread__ = __em.thread(); |
355 | |
356 | #endif // SHARE_UTILITIES_EXCEPTIONS_HPP |
1 | /* |
2 | * Copyright (c) 1997, 2020, 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 | #ifndef SHARE_OOPS_OOPSHIERARCHY_HPP |
26 | #define SHARE_OOPS_OOPSHIERARCHY_HPP |
27 | |
28 | #include "metaprogramming/integralConstant.hpp" |
29 | #include "metaprogramming/primitiveConversions.hpp" |
30 | #include "utilities/globalDefinitions.hpp" |
31 | |
32 | // OBJECT hierarchy |
33 | // This hierarchy is a representation hierarchy, i.e. if A is a superclass |
34 | // of B, A's representation is a prefix of B's representation. |
35 | |
36 | // Global offset instead of address for an oop within a java object. |
37 | enum class narrowOop : uint32_t { null = 0 }; |
38 | |
39 | // If compressed klass pointers then use narrowKlass. |
40 | typedef juint narrowKlass; |
41 | |
42 | typedef void* OopOrNarrowOopStar; |
43 | |
44 | #ifndef CHECK_UNHANDLED_OOPS1 |
45 | |
46 | typedef class oopDesc* oop; |
47 | typedef class instanceOopDesc* instanceOop; |
48 | typedef class arrayOopDesc* arrayOop; |
49 | typedef class objArrayOopDesc* objArrayOop; |
50 | typedef class typeArrayOopDesc* typeArrayOop; |
51 | |
52 | #else |
53 | |
54 | // When CHECK_UNHANDLED_OOPS is defined, an "oop" is a class with a |
55 | // carefully chosen set of constructors and conversion operators to go |
56 | // to and from the underlying oopDesc pointer type. |
57 | // |
58 | // Because oop and its subclasses <type>Oop are class types, arbitrary |
59 | // conversions are not accepted by the compiler. Applying a cast to |
60 | // an oop will cause the best matched conversion operator to be |
61 | // invoked returning the underlying oopDesc* type if appropriate. |
62 | // No copy constructors, explicit user conversions or operators of |
63 | // numerical type should be defined within the oop class. Most C++ |
64 | // compilers will issue a compile time error concerning the overloading |
65 | // ambiguity between operators of numerical and pointer types. If |
66 | // a conversion to or from an oop to a numerical type is needed, |
67 | // use the inline template methods, cast_*_oop, defined below. |
68 | // |
69 | // Converting NULL to oop to Handle implicit is no longer accepted by the |
70 | // compiler because there are too many steps in the conversion. Use Handle() |
71 | // instead, which generates less code anyway. |
72 | |
73 | class Thread; |
74 | class oopDesc; |
75 | |
76 | extern "C" bool CheckUnhandledOops; |
77 | |
78 | class oop { |
79 | oopDesc* _o; |
80 | |
81 | void register_oop(); |
82 | void unregister_oop(); |
83 | |
84 | void register_if_checking() { |
85 | if (CheckUnhandledOops) register_oop(); |
86 | } |
87 | |
88 | public: |
89 | oop() : _o(nullptr) { register_if_checking(); } |
90 | oop(const oop& o) : _o(o._o) { register_if_checking(); } |
91 | oop(oopDesc* o) : _o(o) { register_if_checking(); } |
92 | ~oop() { |
93 | if (CheckUnhandledOops) unregister_oop(); |
94 | } |
95 | |
96 | oopDesc* obj() const { return _o; } |
97 | oopDesc* operator->() const { return _o; } |
98 | operator oopDesc* () const { return _o; } |
99 | |
100 | bool operator==(const oop& o) const { return _o == o._o; } |
101 | bool operator!=(const oop& o) const { return _o != o._o; } |
102 | |
103 | bool operator==(std::nullptr_t) const { return _o == nullptr; } |
104 | bool operator!=(std::nullptr_t) const { return _o != nullptr; } |
105 | |
106 | oop& operator=(const oop& o) { _o = o._o; return *this; } |
107 | }; |
108 | |
109 | template<> |
110 | struct PrimitiveConversions::Translate<oop> : public TrueType { |
111 | typedef oop Value; |
112 | typedef oopDesc* Decayed; |
113 | |
114 | static Decayed decay(Value x) { return x.obj(); } |
115 | static Value recover(Decayed x) { return oop(x); } |
116 | }; |
117 | |
118 | #define DEF_OOP(type)class typeOopDesc; class typeOop : public oop { public: typeOop () : oop() {} typeOop(const typeOop& o) : oop(o) {} typeOop (const oop& o) : oop(o) {} typeOop(typeOopDesc* o) : oop( (oopDesc*)o) {} operator typeOopDesc* () const { return (typeOopDesc *)obj(); } typeOopDesc* operator->() const { return (typeOopDesc *)obj(); } typeOop& operator=(const typeOop& o) { oop ::operator=(o); return *this; } }; template<> struct PrimitiveConversions ::Translate<typeOop> : public TrueType { typedef typeOop Value; typedef typeOopDesc* Decayed; static Decayed decay(Value x) { return (typeOopDesc*)x.obj(); } static Value recover(Decayed x) { return typeOop(x); } }; \ |
119 | class type##OopDesc; \ |
120 | class type##Oop : public oop { \ |
121 | public: \ |
122 | type##Oop() : oop() {} \ |
123 | type##Oop(const type##Oop& o) : oop(o) {} \ |
124 | type##Oop(const oop& o) : oop(o) {} \ |
125 | type##Oop(type##OopDesc* o) : oop((oopDesc*)o) {} \ |
126 | operator type##OopDesc* () const { return (type##OopDesc*)obj(); } \ |
127 | type##OopDesc* operator->() const { \ |
128 | return (type##OopDesc*)obj(); \ |
129 | } \ |
130 | type##Oop& operator=(const type##Oop& o) { \ |
131 | oop::operator=(o); \ |
132 | return *this; \ |
133 | } \ |
134 | }; \ |
135 | \ |
136 | template<> \ |
137 | struct PrimitiveConversions::Translate<type##Oop> : public TrueType { \ |
138 | typedef type##Oop Value; \ |
139 | typedef type##OopDesc* Decayed; \ |
140 | \ |
141 | static Decayed decay(Value x) { return (type##OopDesc*)x.obj(); } \ |
142 | static Value recover(Decayed x) { return type##Oop(x); } \ |
143 | }; |
144 | |
145 | DEF_OOP(instance)class instanceOopDesc; class instanceOop : public oop { public : instanceOop() : oop() {} instanceOop(const instanceOop& o) : oop(o) {} instanceOop(const oop& o) : oop(o) {} instanceOop (instanceOopDesc* o) : oop((oopDesc*)o) {} operator instanceOopDesc * () const { return (instanceOopDesc*)obj(); } instanceOopDesc * operator->() const { return (instanceOopDesc*)obj(); } instanceOop & operator=(const instanceOop& o) { oop::operator=(o) ; return *this; } }; template<> struct PrimitiveConversions ::Translate<instanceOop> : public TrueType { typedef instanceOop Value; typedef instanceOopDesc* Decayed; static Decayed decay (Value x) { return (instanceOopDesc*)x.obj(); } static Value recover (Decayed x) { return instanceOop(x); } };; |
146 | DEF_OOP(array)class arrayOopDesc; class arrayOop : public oop { public: arrayOop () : oop() {} arrayOop(const arrayOop& o) : oop(o) {} arrayOop (const oop& o) : oop(o) {} arrayOop(arrayOopDesc* o) : oop ((oopDesc*)o) {} operator arrayOopDesc* () const { return (arrayOopDesc *)obj(); } arrayOopDesc* operator->() const { return (arrayOopDesc *)obj(); } arrayOop& operator=(const arrayOop& o) { oop ::operator=(o); return *this; } }; template<> struct PrimitiveConversions ::Translate<arrayOop> : public TrueType { typedef arrayOop Value; typedef arrayOopDesc* Decayed; static Decayed decay(Value x) { return (arrayOopDesc*)x.obj(); } static Value recover(Decayed x) { return arrayOop(x); } };; |
147 | DEF_OOP(objArray)class objArrayOopDesc; class objArrayOop : public oop { public : objArrayOop() : oop() {} objArrayOop(const objArrayOop& o) : oop(o) {} objArrayOop(const oop& o) : oop(o) {} objArrayOop (objArrayOopDesc* o) : oop((oopDesc*)o) {} operator objArrayOopDesc * () const { return (objArrayOopDesc*)obj(); } objArrayOopDesc * operator->() const { return (objArrayOopDesc*)obj(); } objArrayOop & operator=(const objArrayOop& o) { oop::operator=(o) ; return *this; } }; template<> struct PrimitiveConversions ::Translate<objArrayOop> : public TrueType { typedef objArrayOop Value; typedef objArrayOopDesc* Decayed; static Decayed decay (Value x) { return (objArrayOopDesc*)x.obj(); } static Value recover (Decayed x) { return objArrayOop(x); } };; |
148 | DEF_OOP(typeArray)class typeArrayOopDesc; class typeArrayOop : public oop { public : typeArrayOop() : oop() {} typeArrayOop(const typeArrayOop& o) : oop(o) {} typeArrayOop(const oop& o) : oop(o) {} typeArrayOop (typeArrayOopDesc* o) : oop((oopDesc*)o) {} operator typeArrayOopDesc * () const { return (typeArrayOopDesc*)obj(); } typeArrayOopDesc * operator->() const { return (typeArrayOopDesc*)obj(); } typeArrayOop & operator=(const typeArrayOop& o) { oop::operator=(o ); return *this; } }; template<> struct PrimitiveConversions ::Translate<typeArrayOop> : public TrueType { typedef typeArrayOop Value; typedef typeArrayOopDesc* Decayed; static Decayed decay (Value x) { return (typeArrayOopDesc*)x.obj(); } static Value recover(Decayed x) { return typeArrayOop(x); } };; |
149 | |
150 | #endif // CHECK_UNHANDLED_OOPS |
151 | |
152 | // Cast functions to convert to and from oops. |
153 | template <typename T> inline oop cast_to_oop(T value) { |
154 | return (oopDesc*)value; |
155 | } |
156 | template <typename T> inline T cast_from_oop(oop o) { |
157 | return (T)(CHECK_UNHANDLED_OOPS_ONLY((oopDesc*))(oopDesc*)o); |
158 | } |
159 | |
160 | // The metadata hierarchy is separate from the oop hierarchy |
161 | |
162 | // class MetaspaceObj |
163 | class ConstMethod; |
164 | class ConstantPoolCache; |
165 | class MethodData; |
166 | // class Metadata |
167 | class Method; |
168 | class ConstantPool; |
169 | // class CHeapObj |
170 | class CompiledICHolder; |
171 | |
172 | |
173 | // The klass hierarchy is separate from the oop hierarchy. |
174 | |
175 | class Klass; |
176 | class InstanceKlass; |
177 | class InstanceMirrorKlass; |
178 | class InstanceClassLoaderKlass; |
179 | class InstanceRefKlass; |
180 | class ArrayKlass; |
181 | class ObjArrayKlass; |
182 | class TypeArrayKlass; |
183 | |
184 | #endif // SHARE_OOPS_OOPSHIERARCHY_HPP |
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 | #ifndef SHARE_CLASSFILE_CLASSFILEPARSER_HPP | ||||||||||||
26 | #define SHARE_CLASSFILE_CLASSFILEPARSER_HPP | ||||||||||||
27 | |||||||||||||
28 | #include "memory/referenceType.hpp" | ||||||||||||
29 | #include "oops/annotations.hpp" | ||||||||||||
30 | #include "oops/constantPool.hpp" | ||||||||||||
31 | #include "oops/instanceKlass.hpp" | ||||||||||||
32 | #include "oops/typeArrayOop.hpp" | ||||||||||||
33 | #include "utilities/accessFlags.hpp" | ||||||||||||
34 | |||||||||||||
35 | class Annotations; | ||||||||||||
36 | template <typename T> | ||||||||||||
37 | class Array; | ||||||||||||
38 | class ClassFileStream; | ||||||||||||
39 | class ClassLoaderData; | ||||||||||||
40 | class ClassLoadInfo; | ||||||||||||
41 | class ClassInstanceInfo; | ||||||||||||
42 | class CompressedLineNumberWriteStream; | ||||||||||||
43 | class ConstMethod; | ||||||||||||
44 | class FieldInfo; | ||||||||||||
45 | template <typename T> | ||||||||||||
46 | class GrowableArray; | ||||||||||||
47 | class InstanceKlass; | ||||||||||||
48 | class RecordComponent; | ||||||||||||
49 | class Symbol; | ||||||||||||
50 | class TempNewSymbol; | ||||||||||||
51 | class FieldLayoutBuilder; | ||||||||||||
52 | |||||||||||||
53 | // Utility to collect and compact oop maps during layout | ||||||||||||
54 | class OopMapBlocksBuilder : public ResourceObj { | ||||||||||||
55 | public: | ||||||||||||
56 | OopMapBlock* _nonstatic_oop_maps; | ||||||||||||
57 | unsigned int _nonstatic_oop_map_count; | ||||||||||||
58 | unsigned int _max_nonstatic_oop_maps; | ||||||||||||
59 | |||||||||||||
60 | OopMapBlocksBuilder(unsigned int max_blocks); | ||||||||||||
61 | OopMapBlock* last_oop_map() const; | ||||||||||||
62 | void initialize_inherited_blocks(OopMapBlock* blocks, unsigned int nof_blocks); | ||||||||||||
63 | void add(int offset, int count); | ||||||||||||
64 | void copy(OopMapBlock* dst); | ||||||||||||
65 | void compact(); | ||||||||||||
66 | void print_on(outputStream* st) const; | ||||||||||||
67 | void print_value_on(outputStream* st) const; | ||||||||||||
68 | }; | ||||||||||||
69 | |||||||||||||
70 | // Values needed for oopmap and InstanceKlass creation | ||||||||||||
71 | class FieldLayoutInfo : public ResourceObj { | ||||||||||||
72 | public: | ||||||||||||
73 | OopMapBlocksBuilder* oop_map_blocks; | ||||||||||||
74 | int _instance_size; | ||||||||||||
75 | int _nonstatic_field_size; | ||||||||||||
76 | int _static_field_size; | ||||||||||||
77 | bool _has_nonstatic_fields; | ||||||||||||
78 | }; | ||||||||||||
79 | |||||||||||||
80 | // Parser for for .class files | ||||||||||||
81 | // | ||||||||||||
82 | // The bytes describing the class file structure is read from a Stream object | ||||||||||||
83 | |||||||||||||
84 | class ClassFileParser { | ||||||||||||
85 | friend class FieldLayoutBuilder; | ||||||||||||
86 | friend class FieldLayout; | ||||||||||||
87 | |||||||||||||
88 | class ClassAnnotationCollector; | ||||||||||||
89 | class FieldAllocationCount; | ||||||||||||
90 | class FieldAnnotationCollector; | ||||||||||||
91 | |||||||||||||
92 | public: | ||||||||||||
93 | // The ClassFileParser has an associated "publicity" level | ||||||||||||
94 | // It is used to control which subsystems (if any) | ||||||||||||
95 | // will observe the parsing (logging, events, tracing). | ||||||||||||
96 | // Default level is "BROADCAST", which is equivalent to | ||||||||||||
97 | // a "public" parsing attempt. | ||||||||||||
98 | // | ||||||||||||
99 | // "INTERNAL" level should be entirely private to the | ||||||||||||
100 | // caller - this allows for internal reuse of ClassFileParser | ||||||||||||
101 | // | ||||||||||||
102 | enum Publicity { | ||||||||||||
103 | INTERNAL, | ||||||||||||
104 | BROADCAST | ||||||||||||
105 | }; | ||||||||||||
106 | |||||||||||||
107 | enum { LegalClass, LegalField, LegalMethod }; // used to verify unqualified names | ||||||||||||
108 | |||||||||||||
109 | private: | ||||||||||||
110 | // Potentially unaligned pointer to various 16-bit entries in the class file | ||||||||||||
111 | typedef void unsafe_u2; | ||||||||||||
112 | |||||||||||||
113 | const ClassFileStream* _stream; // Actual input stream | ||||||||||||
114 | Symbol* _class_name; | ||||||||||||
115 | mutable ClassLoaderData* _loader_data; | ||||||||||||
116 | const bool _is_hidden; | ||||||||||||
117 | const bool _can_access_vm_annotations; | ||||||||||||
118 | int _orig_cp_size; | ||||||||||||
119 | |||||||||||||
120 | // Metadata created before the instance klass is created. Must be deallocated | ||||||||||||
121 | // if not transferred to the InstanceKlass upon successful class loading | ||||||||||||
122 | // in which case these pointers have been set to NULL. | ||||||||||||
123 | const InstanceKlass* _super_klass; | ||||||||||||
124 | ConstantPool* _cp; | ||||||||||||
125 | Array<u2>* _fields; | ||||||||||||
126 | Array<Method*>* _methods; | ||||||||||||
127 | Array<u2>* _inner_classes; | ||||||||||||
128 | Array<u2>* _nest_members; | ||||||||||||
129 | u2 _nest_host; | ||||||||||||
130 | Array<u2>* _permitted_subclasses; | ||||||||||||
131 | Array<RecordComponent*>* _record_components; | ||||||||||||
132 | Array<InstanceKlass*>* _local_interfaces; | ||||||||||||
133 | Array<InstanceKlass*>* _transitive_interfaces; | ||||||||||||
134 | Annotations* _combined_annotations; | ||||||||||||
135 | AnnotationArray* _class_annotations; | ||||||||||||
136 | AnnotationArray* _class_type_annotations; | ||||||||||||
137 | Array<AnnotationArray*>* _fields_annotations; | ||||||||||||
138 | Array<AnnotationArray*>* _fields_type_annotations; | ||||||||||||
139 | InstanceKlass* _klass; // InstanceKlass* once created. | ||||||||||||
140 | InstanceKlass* _klass_to_deallocate; // an InstanceKlass* to be destroyed | ||||||||||||
141 | |||||||||||||
142 | ClassAnnotationCollector* _parsed_annotations; | ||||||||||||
143 | FieldAllocationCount* _fac; | ||||||||||||
144 | FieldLayoutInfo* _field_info; | ||||||||||||
145 | const intArray* _method_ordering; | ||||||||||||
146 | GrowableArray<Method*>* _all_mirandas; | ||||||||||||
147 | |||||||||||||
148 | enum { fixed_buffer_size = 128 }; | ||||||||||||
149 | u_char _linenumbertable_buffer[fixed_buffer_size]; | ||||||||||||
150 | |||||||||||||
151 | // Size of Java vtable (in words) | ||||||||||||
152 | int _vtable_size; | ||||||||||||
153 | int _itable_size; | ||||||||||||
154 | |||||||||||||
155 | int _num_miranda_methods; | ||||||||||||
156 | |||||||||||||
157 | ReferenceType _rt; | ||||||||||||
158 | Handle _protection_domain; | ||||||||||||
159 | AccessFlags _access_flags; | ||||||||||||
160 | |||||||||||||
161 | // for tracing and notifications | ||||||||||||
162 | Publicity _pub_level; | ||||||||||||
163 | |||||||||||||
164 | // Used to keep track of whether a constant pool item 19 or 20 is found. These | ||||||||||||
165 | // correspond to CONSTANT_Module and CONSTANT_Package tags and are not allowed | ||||||||||||
166 | // in regular class files. For class file version >= 53, a CFE cannot be thrown | ||||||||||||
167 | // immediately when these are seen because a NCDFE must be thrown if the class's | ||||||||||||
168 | // access_flags have ACC_MODULE set. But, the access_flags haven't been looked | ||||||||||||
169 | // at yet. So, the bad constant pool item is cached here. A value of zero | ||||||||||||
170 | // means that no constant pool item 19 or 20 was found. | ||||||||||||
171 | short _bad_constant_seen; | ||||||||||||
172 | |||||||||||||
173 | // class attributes parsed before the instance klass is created: | ||||||||||||
174 | bool _synthetic_flag; | ||||||||||||
175 | int _sde_length; | ||||||||||||
176 | const char* _sde_buffer; | ||||||||||||
177 | u2 _sourcefile_index; | ||||||||||||
178 | u2 _generic_signature_index; | ||||||||||||
179 | |||||||||||||
180 | u2 _major_version; | ||||||||||||
181 | u2 _minor_version; | ||||||||||||
182 | u2 _this_class_index; | ||||||||||||
183 | u2 _super_class_index; | ||||||||||||
184 | u2 _itfs_len; | ||||||||||||
185 | u2 _java_fields_count; | ||||||||||||
186 | |||||||||||||
187 | bool _need_verify; | ||||||||||||
188 | bool _relax_verify; | ||||||||||||
189 | |||||||||||||
190 | bool _has_nonstatic_concrete_methods; | ||||||||||||
191 | bool _declares_nonstatic_concrete_methods; | ||||||||||||
192 | bool _has_final_method; | ||||||||||||
193 | bool _has_contended_fields; | ||||||||||||
194 | |||||||||||||
195 | // precomputed flags | ||||||||||||
196 | bool _has_finalizer; | ||||||||||||
197 | bool _has_empty_finalizer; | ||||||||||||
198 | bool _has_vanilla_constructor; | ||||||||||||
199 | int _max_bootstrap_specifier_index; // detects BSS values | ||||||||||||
200 | |||||||||||||
201 | void parse_stream(const ClassFileStream* const stream, TRAPSJavaThread* __the_thread__); | ||||||||||||
202 | |||||||||||||
203 | void mangle_hidden_class_name(InstanceKlass* const ik); | ||||||||||||
204 | |||||||||||||
205 | void post_process_parsed_stream(const ClassFileStream* const stream, | ||||||||||||
206 | ConstantPool* cp, | ||||||||||||
207 | TRAPSJavaThread* __the_thread__); | ||||||||||||
208 | |||||||||||||
209 | void fill_instance_klass(InstanceKlass* ik, bool cf_changed_in_CFLH, | ||||||||||||
210 | const ClassInstanceInfo& cl_inst_info, TRAPSJavaThread* __the_thread__); | ||||||||||||
211 | |||||||||||||
212 | void set_klass(InstanceKlass* instance); | ||||||||||||
213 | |||||||||||||
214 | void set_class_bad_constant_seen(short bad_constant); | ||||||||||||
215 | short class_bad_constant_seen() { return _bad_constant_seen; } | ||||||||||||
216 | void set_class_synthetic_flag(bool x) { _synthetic_flag = x; } | ||||||||||||
217 | void set_class_sourcefile_index(u2 x) { _sourcefile_index = x; } | ||||||||||||
218 | void set_class_generic_signature_index(u2 x) { _generic_signature_index = x; } | ||||||||||||
219 | void set_class_sde_buffer(const char* x, int len) { _sde_buffer = x; _sde_length = len; } | ||||||||||||
220 | |||||||||||||
221 | void create_combined_annotations(TRAPSJavaThread* __the_thread__); | ||||||||||||
222 | void apply_parsed_class_attributes(InstanceKlass* k); // update k | ||||||||||||
223 | void apply_parsed_class_metadata(InstanceKlass* k, int fields_count); | ||||||||||||
224 | void clear_class_metadata(); | ||||||||||||
225 | |||||||||||||
226 | // Constant pool parsing | ||||||||||||
227 | void parse_constant_pool_entries(const ClassFileStream* const stream, | ||||||||||||
228 | ConstantPool* cp, | ||||||||||||
229 | const int length, | ||||||||||||
230 | TRAPSJavaThread* __the_thread__); | ||||||||||||
231 | |||||||||||||
232 | void parse_constant_pool(const ClassFileStream* const cfs, | ||||||||||||
233 | ConstantPool* const cp, | ||||||||||||
234 | const int length, | ||||||||||||
235 | TRAPSJavaThread* __the_thread__); | ||||||||||||
236 | |||||||||||||
237 | // Interface parsing | ||||||||||||
238 | void parse_interfaces(const ClassFileStream* const stream, | ||||||||||||
239 | const int itfs_len, | ||||||||||||
240 | ConstantPool* const cp, | ||||||||||||
241 | bool* has_nonstatic_concrete_methods, | ||||||||||||
242 | TRAPSJavaThread* __the_thread__); | ||||||||||||
243 | |||||||||||||
244 | const InstanceKlass* parse_super_class(ConstantPool* const cp, | ||||||||||||
245 | const int super_class_index, | ||||||||||||
246 | const bool need_verify, | ||||||||||||
247 | TRAPSJavaThread* __the_thread__); | ||||||||||||
248 | |||||||||||||
249 | // Field parsing | ||||||||||||
250 | void parse_field_attributes(const ClassFileStream* const cfs, | ||||||||||||
251 | u2 attributes_count, | ||||||||||||
252 | bool is_static, | ||||||||||||
253 | u2 signature_index, | ||||||||||||
254 | u2* const constantvalue_index_addr, | ||||||||||||
255 | bool* const is_synthetic_addr, | ||||||||||||
256 | u2* const generic_signature_index_addr, | ||||||||||||
257 | FieldAnnotationCollector* parsed_annotations, | ||||||||||||
258 | TRAPSJavaThread* __the_thread__); | ||||||||||||
259 | |||||||||||||
260 | void parse_fields(const ClassFileStream* const cfs, | ||||||||||||
261 | bool is_interface, | ||||||||||||
262 | FieldAllocationCount* const fac, | ||||||||||||
263 | ConstantPool* cp, | ||||||||||||
264 | const int cp_size, | ||||||||||||
265 | u2* const java_fields_count_ptr, | ||||||||||||
266 | TRAPSJavaThread* __the_thread__); | ||||||||||||
267 | |||||||||||||
268 | // Method parsing | ||||||||||||
269 | Method* parse_method(const ClassFileStream* const cfs, | ||||||||||||
270 | bool is_interface, | ||||||||||||
271 | const ConstantPool* cp, | ||||||||||||
272 | AccessFlags* const promoted_flags, | ||||||||||||
273 | TRAPSJavaThread* __the_thread__); | ||||||||||||
274 | |||||||||||||
275 | void parse_methods(const ClassFileStream* const cfs, | ||||||||||||
276 | bool is_interface, | ||||||||||||
277 | AccessFlags* const promoted_flags, | ||||||||||||
278 | bool* const has_final_method, | ||||||||||||
279 | bool* const declares_nonstatic_concrete_methods, | ||||||||||||
280 | TRAPSJavaThread* __the_thread__); | ||||||||||||
281 | |||||||||||||
282 | const unsafe_u2* parse_exception_table(const ClassFileStream* const stream, | ||||||||||||
283 | u4 code_length, | ||||||||||||
284 | u4 exception_table_length, | ||||||||||||
285 | TRAPSJavaThread* __the_thread__); | ||||||||||||
286 | |||||||||||||
287 | void parse_linenumber_table(u4 code_attribute_length, | ||||||||||||
288 | u4 code_length, | ||||||||||||
289 | CompressedLineNumberWriteStream**const write_stream, | ||||||||||||
290 | TRAPSJavaThread* __the_thread__); | ||||||||||||
291 | |||||||||||||
292 | const unsafe_u2* parse_localvariable_table(const ClassFileStream* const cfs, | ||||||||||||
293 | u4 code_length, | ||||||||||||
294 | u2 max_locals, | ||||||||||||
295 | u4 code_attribute_length, | ||||||||||||
296 | u2* const localvariable_table_length, | ||||||||||||
297 | bool isLVTT, | ||||||||||||
298 | TRAPSJavaThread* __the_thread__); | ||||||||||||
299 | |||||||||||||
300 | const unsafe_u2* parse_checked_exceptions(const ClassFileStream* const cfs, | ||||||||||||
301 | u2* const checked_exceptions_length, | ||||||||||||
302 | u4 method_attribute_length, | ||||||||||||
303 | TRAPSJavaThread* __the_thread__); | ||||||||||||
304 | |||||||||||||
305 | // Classfile attribute parsing | ||||||||||||
306 | u2 parse_generic_signature_attribute(const ClassFileStream* const cfs, TRAPSJavaThread* __the_thread__); | ||||||||||||
307 | void parse_classfile_sourcefile_attribute(const ClassFileStream* const cfs, TRAPSJavaThread* __the_thread__); | ||||||||||||
308 | void parse_classfile_source_debug_extension_attribute(const ClassFileStream* const cfs, | ||||||||||||
309 | int length, | ||||||||||||
310 | TRAPSJavaThread* __the_thread__); | ||||||||||||
311 | |||||||||||||
312 | // Check for circularity in InnerClasses attribute. | ||||||||||||
313 | bool check_inner_classes_circularity(const ConstantPool* cp, int length, TRAPSJavaThread* __the_thread__); | ||||||||||||
314 | |||||||||||||
315 | u2 parse_classfile_inner_classes_attribute(const ClassFileStream* const cfs, | ||||||||||||
316 | const ConstantPool* cp, | ||||||||||||
317 | const u1* const inner_classes_attribute_start, | ||||||||||||
318 | bool parsed_enclosingmethod_attribute, | ||||||||||||
319 | u2 enclosing_method_class_index, | ||||||||||||
320 | u2 enclosing_method_method_index, | ||||||||||||
321 | TRAPSJavaThread* __the_thread__); | ||||||||||||
322 | |||||||||||||
323 | u2 parse_classfile_nest_members_attribute(const ClassFileStream* const cfs, | ||||||||||||
324 | const u1* const nest_members_attribute_start, | ||||||||||||
325 | TRAPSJavaThread* __the_thread__); | ||||||||||||
326 | |||||||||||||
327 | u2 parse_classfile_permitted_subclasses_attribute(const ClassFileStream* const cfs, | ||||||||||||
328 | const u1* const permitted_subclasses_attribute_start, | ||||||||||||
329 | TRAPSJavaThread* __the_thread__); | ||||||||||||
330 | |||||||||||||
331 | u2 parse_classfile_record_attribute(const ClassFileStream* const cfs, | ||||||||||||
332 | const ConstantPool* cp, | ||||||||||||
333 | const u1* const record_attribute_start, | ||||||||||||
334 | TRAPSJavaThread* __the_thread__); | ||||||||||||
335 | |||||||||||||
336 | void parse_classfile_attributes(const ClassFileStream* const cfs, | ||||||||||||
337 | ConstantPool* cp, | ||||||||||||
338 | ClassAnnotationCollector* parsed_annotations, | ||||||||||||
339 | TRAPSJavaThread* __the_thread__); | ||||||||||||
340 | |||||||||||||
341 | void parse_classfile_synthetic_attribute(); | ||||||||||||
342 | void parse_classfile_signature_attribute(const ClassFileStream* const cfs, TRAPSJavaThread* __the_thread__); | ||||||||||||
343 | void parse_classfile_bootstrap_methods_attribute(const ClassFileStream* const cfs, | ||||||||||||
344 | ConstantPool* cp, | ||||||||||||
345 | u4 attribute_length, | ||||||||||||
346 | TRAPSJavaThread* __the_thread__); | ||||||||||||
347 | |||||||||||||
348 | // Annotations handling | ||||||||||||
349 | AnnotationArray* assemble_annotations(const u1* const runtime_visible_annotations, | ||||||||||||
350 | int runtime_visible_annotations_length, | ||||||||||||
351 | const u1* const runtime_invisible_annotations, | ||||||||||||
352 | int runtime_invisible_annotations_length, | ||||||||||||
353 | TRAPSJavaThread* __the_thread__); | ||||||||||||
354 | |||||||||||||
355 | void set_precomputed_flags(InstanceKlass* k); | ||||||||||||
356 | |||||||||||||
357 | // Format checker methods | ||||||||||||
358 | void classfile_parse_error(const char* msg, TRAPSJavaThread* __the_thread__) const; | ||||||||||||
359 | void classfile_parse_error(const char* msg, int index, TRAPSJavaThread* __the_thread__) const; | ||||||||||||
360 | void classfile_parse_error(const char* msg, const char *name, TRAPSJavaThread* __the_thread__) const; | ||||||||||||
361 | void classfile_parse_error(const char* msg, | ||||||||||||
362 | int index, | ||||||||||||
363 | const char *name, | ||||||||||||
364 | TRAPSJavaThread* __the_thread__) const; | ||||||||||||
365 | void classfile_parse_error(const char* msg, | ||||||||||||
366 | const char* name, | ||||||||||||
367 | const char* signature, | ||||||||||||
368 | TRAPSJavaThread* __the_thread__) const; | ||||||||||||
369 | |||||||||||||
370 | void classfile_icce_error(const char* msg, | ||||||||||||
371 | const Klass* k, | ||||||||||||
372 | TRAPSJavaThread* __the_thread__) const; | ||||||||||||
373 | |||||||||||||
374 | void classfile_ucve_error(const char* msg, | ||||||||||||
375 | const Symbol* class_name, | ||||||||||||
376 | u2 major, | ||||||||||||
377 | u2 minor, | ||||||||||||
378 | TRAPSJavaThread* __the_thread__) const; | ||||||||||||
379 | |||||||||||||
380 | inline void guarantee_property(bool b, const char* msg, TRAPSJavaThread* __the_thread__) const { | ||||||||||||
381 | if (!b) { classfile_parse_error(msg, THREAD__the_thread__); return; } | ||||||||||||
382 | } | ||||||||||||
383 | |||||||||||||
384 | void report_assert_property_failure(const char* msg, TRAPSJavaThread* __the_thread__) const PRODUCT_RETURN; | ||||||||||||
385 | void report_assert_property_failure(const char* msg, int index, TRAPSJavaThread* __the_thread__) const PRODUCT_RETURN; | ||||||||||||
386 | |||||||||||||
387 | inline void assert_property(bool b, const char* msg, TRAPSJavaThread* __the_thread__) const { | ||||||||||||
388 | #ifdef ASSERT1 | ||||||||||||
389 | if (!b) { | ||||||||||||
390 | report_assert_property_failure(msg, THREAD__the_thread__); | ||||||||||||
391 | } | ||||||||||||
392 | #endif | ||||||||||||
393 | } | ||||||||||||
394 | |||||||||||||
395 | inline void assert_property(bool b, const char* msg, int index, TRAPSJavaThread* __the_thread__) const { | ||||||||||||
396 | #ifdef ASSERT1 | ||||||||||||
397 | if (!b) { | ||||||||||||
398 | report_assert_property_failure(msg, index, THREAD__the_thread__); | ||||||||||||
399 | } | ||||||||||||
400 | #endif | ||||||||||||
401 | } | ||||||||||||
402 | |||||||||||||
403 | inline void check_property(bool property, | ||||||||||||
404 | const char* msg, | ||||||||||||
405 | int index, | ||||||||||||
406 | TRAPSJavaThread* __the_thread__) const { | ||||||||||||
407 | if (_need_verify) { | ||||||||||||
408 | guarantee_property(property, msg, index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
409 | } else { | ||||||||||||
410 | assert_property(property, msg, index, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
411 | } | ||||||||||||
412 | } | ||||||||||||
413 | |||||||||||||
414 | inline void check_property(bool property, const char* msg, TRAPSJavaThread* __the_thread__) const { | ||||||||||||
415 | if (_need_verify) { | ||||||||||||
416 | guarantee_property(property, msg, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
417 | } else { | ||||||||||||
418 | assert_property(property, msg, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | ||||||||||||
419 | } | ||||||||||||
420 | } | ||||||||||||
421 | |||||||||||||
422 | inline void guarantee_property(bool b, | ||||||||||||
423 | const char* msg, | ||||||||||||
424 | int index, | ||||||||||||
425 | TRAPSJavaThread* __the_thread__) const { | ||||||||||||
426 | if (!b
| ||||||||||||
427 | } | ||||||||||||
428 | |||||||||||||
429 | inline void guarantee_property(bool b, | ||||||||||||
430 | const char* msg, | ||||||||||||
431 | const char *name, | ||||||||||||
432 | TRAPSJavaThread* __the_thread__) const { | ||||||||||||
433 | if (!b) { classfile_parse_error(msg, name, THREAD__the_thread__); return; } | ||||||||||||
434 | } | ||||||||||||
435 | |||||||||||||
436 | inline void guarantee_property(bool b, | ||||||||||||
437 | const char* msg, | ||||||||||||
438 | int index, | ||||||||||||
439 | const char *name, | ||||||||||||
440 | TRAPSJavaThread* __the_thread__) const { | ||||||||||||
441 | if (!b) { classfile_parse_error(msg, index, name, THREAD__the_thread__); return; } | ||||||||||||
442 | } | ||||||||||||
443 | |||||||||||||
444 | void throwIllegalSignature(const char* type, | ||||||||||||
445 | const Symbol* name, | ||||||||||||
446 | const Symbol* sig, | ||||||||||||
447 | TRAPSJavaThread* __the_thread__) const; | ||||||||||||
448 | |||||||||||||
449 | void verify_constantvalue(const ConstantPool* const cp, | ||||||||||||
450 | int constantvalue_index, | ||||||||||||
451 | int signature_index, | ||||||||||||
452 | TRAPSJavaThread* __the_thread__) const; | ||||||||||||
453 | |||||||||||||
454 | void verify_legal_utf8(const unsigned char* buffer, int length, TRAPSJavaThread* __the_thread__) const; | ||||||||||||
455 | void verify_legal_class_name(const Symbol* name, TRAPSJavaThread* __the_thread__) const; | ||||||||||||
456 | void verify_legal_field_name(const Symbol* name, TRAPSJavaThread* __the_thread__) const; | ||||||||||||
457 | void verify_legal_method_name(const Symbol* name, TRAPSJavaThread* __the_thread__) const; | ||||||||||||
458 | |||||||||||||
459 | void verify_legal_field_signature(const Symbol* fieldname, | ||||||||||||
460 | const Symbol* signature, | ||||||||||||
461 | TRAPSJavaThread* __the_thread__) const; | ||||||||||||
462 | int verify_legal_method_signature(const Symbol* methodname, | ||||||||||||
463 | const Symbol* signature, | ||||||||||||
464 | TRAPSJavaThread* __the_thread__) const; | ||||||||||||
465 | void verify_legal_name_with_signature(const Symbol* name, | ||||||||||||
466 | const Symbol* signature, | ||||||||||||
467 | TRAPSJavaThread* __the_thread__) const; | ||||||||||||
468 | |||||||||||||
469 | void verify_class_version(u2 major, u2 minor, Symbol* class_name, TRAPSJavaThread* __the_thread__); | ||||||||||||
470 | |||||||||||||
471 | void verify_legal_class_modifiers(jint flags, TRAPSJavaThread* __the_thread__) const; | ||||||||||||
472 | void verify_legal_field_modifiers(jint flags, bool is_interface, TRAPSJavaThread* __the_thread__) const; | ||||||||||||
473 | void verify_legal_method_modifiers(jint flags, | ||||||||||||
474 | bool is_interface, | ||||||||||||
475 | const Symbol* name, | ||||||||||||
476 | TRAPSJavaThread* __the_thread__) const; | ||||||||||||
477 | |||||||||||||
478 | void check_super_class_access(const InstanceKlass* this_klass, | ||||||||||||
479 | TRAPSJavaThread* __the_thread__); | ||||||||||||
480 | |||||||||||||
481 | void check_super_interface_access(const InstanceKlass* this_klass, | ||||||||||||
482 | TRAPSJavaThread* __the_thread__); | ||||||||||||
483 | |||||||||||||
484 | const char* skip_over_field_signature(const char* signature, | ||||||||||||
485 | bool void_ok, | ||||||||||||
486 | unsigned int length, | ||||||||||||
487 | TRAPSJavaThread* __the_thread__) const; | ||||||||||||
488 | |||||||||||||
489 | // Wrapper for constantTag.is_klass_[or_]reference. | ||||||||||||
490 | // In older versions of the VM, Klass*s cannot sneak into early phases of | ||||||||||||
491 | // constant pool construction, but in later versions they can. | ||||||||||||
492 | // %%% Let's phase out the old is_klass_reference. | ||||||||||||
493 | bool valid_klass_reference_at(int index) const { | ||||||||||||
494 | return _cp->is_within_bounds(index) && | ||||||||||||
495 | _cp->tag_at(index).is_klass_or_reference(); | ||||||||||||
496 | } | ||||||||||||
497 | |||||||||||||
498 | // Checks that the cpool index is in range and is a utf8 | ||||||||||||
499 | bool valid_symbol_at(int cpool_index) const { | ||||||||||||
500 | return _cp->is_within_bounds(cpool_index) && | ||||||||||||
501 | _cp->tag_at(cpool_index).is_utf8(); | ||||||||||||
502 | } | ||||||||||||
503 | |||||||||||||
504 | void copy_localvariable_table(const ConstMethod* cm, | ||||||||||||
505 | int lvt_cnt, | ||||||||||||
506 | u2* const localvariable_table_length, | ||||||||||||
507 | const unsafe_u2** const localvariable_table_start, | ||||||||||||
508 | int lvtt_cnt, | ||||||||||||
509 | u2* const localvariable_type_table_length, | ||||||||||||
510 | const unsafe_u2** const localvariable_type_table_start, | ||||||||||||
511 | TRAPSJavaThread* __the_thread__); | ||||||||||||
512 | |||||||||||||
513 | void copy_method_annotations(ConstMethod* cm, | ||||||||||||
514 | const u1* runtime_visible_annotations, | ||||||||||||
515 | int runtime_visible_annotations_length, | ||||||||||||
516 | const u1* runtime_invisible_annotations, | ||||||||||||
517 | int runtime_invisible_annotations_length, | ||||||||||||
518 | const u1* runtime_visible_parameter_annotations, | ||||||||||||
519 | int runtime_visible_parameter_annotations_length, | ||||||||||||
520 | const u1* runtime_invisible_parameter_annotations, | ||||||||||||
521 | int runtime_invisible_parameter_annotations_length, | ||||||||||||
522 | const u1* runtime_visible_type_annotations, | ||||||||||||
523 | int runtime_visible_type_annotations_length, | ||||||||||||
524 | const u1* runtime_invisible_type_annotations, | ||||||||||||
525 | int runtime_invisible_type_annotations_length, | ||||||||||||
526 | const u1* annotation_default, | ||||||||||||
527 | int annotation_default_length, | ||||||||||||
528 | TRAPSJavaThread* __the_thread__); | ||||||||||||
529 | |||||||||||||
530 | void update_class_name(Symbol* new_name); | ||||||||||||
531 | |||||||||||||
532 | public: | ||||||||||||
533 | ClassFileParser(ClassFileStream* stream, | ||||||||||||
534 | Symbol* name, | ||||||||||||
535 | ClassLoaderData* loader_data, | ||||||||||||
536 | const ClassLoadInfo* cl_info, | ||||||||||||
537 | Publicity pub_level, | ||||||||||||
538 | TRAPSJavaThread* __the_thread__); | ||||||||||||
539 | |||||||||||||
540 | ~ClassFileParser(); | ||||||||||||
541 | |||||||||||||
542 | InstanceKlass* create_instance_klass(bool cf_changed_in_CFLH, const ClassInstanceInfo& cl_inst_info, TRAPSJavaThread* __the_thread__); | ||||||||||||
543 | |||||||||||||
544 | const ClassFileStream* clone_stream() const; | ||||||||||||
545 | |||||||||||||
546 | void set_klass_to_deallocate(InstanceKlass* klass); | ||||||||||||
547 | |||||||||||||
548 | int static_field_size() const; | ||||||||||||
549 | int total_oop_map_count() const; | ||||||||||||
550 | jint layout_size() const; | ||||||||||||
551 | |||||||||||||
552 | int vtable_size() const { return _vtable_size; } | ||||||||||||
553 | int itable_size() const { return _itable_size; } | ||||||||||||
554 | |||||||||||||
555 | u2 this_class_index() const { return _this_class_index; } | ||||||||||||
556 | |||||||||||||
557 | bool is_hidden() const { return _is_hidden; } | ||||||||||||
558 | bool is_interface() const { return _access_flags.is_interface(); } | ||||||||||||
559 | |||||||||||||
560 | ClassLoaderData* loader_data() const { return _loader_data; } | ||||||||||||
561 | const Symbol* class_name() const { return _class_name; } | ||||||||||||
562 | const InstanceKlass* super_klass() const { return _super_klass; } | ||||||||||||
563 | |||||||||||||
564 | ReferenceType reference_type() const { return _rt; } | ||||||||||||
565 | AccessFlags access_flags() const { return _access_flags; } | ||||||||||||
566 | |||||||||||||
567 | bool is_internal() const { return INTERNAL == _pub_level; } | ||||||||||||
568 | |||||||||||||
569 | static bool verify_unqualified_name(const char* name, unsigned int length, int type); | ||||||||||||
570 | |||||||||||||
571 | #ifdef ASSERT1 | ||||||||||||
572 | static bool is_internal_format(Symbol* class_name); | ||||||||||||
573 | #endif | ||||||||||||
574 | |||||||||||||
575 | }; | ||||||||||||
576 | |||||||||||||
577 | #endif // SHARE_CLASSFILE_CLASSFILEPARSER_HPP |
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 | #ifndef SHARE_OOPS_METHOD_HPP |
26 | #define SHARE_OOPS_METHOD_HPP |
27 | |
28 | #include "code/compressedStream.hpp" |
29 | #include "compiler/compilerDefinitions.hpp" |
30 | #include "interpreter/invocationCounter.hpp" |
31 | #include "oops/annotations.hpp" |
32 | #include "oops/constantPool.hpp" |
33 | #include "oops/methodCounters.hpp" |
34 | #include "oops/instanceKlass.hpp" |
35 | #include "oops/oop.hpp" |
36 | #include "oops/typeArrayOop.hpp" |
37 | #include "utilities/accessFlags.hpp" |
38 | #include "utilities/align.hpp" |
39 | #include "utilities/growableArray.hpp" |
40 | #include "utilities/macros.hpp" |
41 | #include "utilities/vmEnums.hpp" |
42 | #if INCLUDE_JFR1 |
43 | #include "jfr/support/jfrTraceIdExtension.hpp" |
44 | #endif |
45 | |
46 | |
47 | // A Method represents a Java method. |
48 | // |
49 | // Note that most applications load thousands of methods, so keeping the size of this |
50 | // class small has a big impact on footprint. |
51 | // |
52 | // Note that native_function and signature_handler have to be at fixed offsets |
53 | // (required by the interpreter) |
54 | // |
55 | // Method embedded field layout (after declared fields): |
56 | // [EMBEDDED native_function (present only if native) ] |
57 | // [EMBEDDED signature_handler (present only if native) ] |
58 | |
59 | class CheckedExceptionElement; |
60 | class LocalVariableTableElement; |
61 | class AdapterHandlerEntry; |
62 | class MethodData; |
63 | class MethodCounters; |
64 | class ConstMethod; |
65 | class InlineTableSizes; |
66 | class CompiledMethod; |
67 | class InterpreterOopMap; |
68 | |
69 | class Method : public Metadata { |
70 | friend class VMStructs; |
71 | friend class JVMCIVMStructs; |
72 | private: |
73 | // If you add a new field that points to any metaspace object, you |
74 | // must add this field to Method::metaspace_pointers_do(). |
75 | ConstMethod* _constMethod; // Method read-only data. |
76 | MethodData* _method_data; |
77 | MethodCounters* _method_counters; |
78 | AdapterHandlerEntry* _adapter; |
79 | AccessFlags _access_flags; // Access flags |
80 | int _vtable_index; // vtable index of this method (see VtableIndexFlag) |
81 | // note: can have vtables with >2**16 elements (because of inheritance) |
82 | u2 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none) |
83 | |
84 | // Flags |
85 | enum Flags { |
86 | _caller_sensitive = 1 << 0, |
87 | _force_inline = 1 << 1, |
88 | _dont_inline = 1 << 2, |
89 | _hidden = 1 << 3, |
90 | _has_injected_profile = 1 << 4, |
91 | _intrinsic_candidate = 1 << 5, |
92 | _reserved_stack_access = 1 << 6, |
93 | _scoped = 1 << 7 |
94 | }; |
95 | mutable u2 _flags; |
96 | |
97 | JFR_ONLY(DEFINE_TRACE_FLAG;)mutable JfrTraceFlag _trace_flags; |
98 | |
99 | #ifndef PRODUCT |
100 | int64_t _compiled_invocation_count; |
101 | #endif |
102 | // Entry point for calling both from and to the interpreter. |
103 | address _i2i_entry; // All-args-on-stack calling convention |
104 | // Entry point for calling from compiled code, to compiled code if it exists |
105 | // or else the interpreter. |
106 | volatile address _from_compiled_entry; // Cache of: _code ? _code->entry_point() : _adapter->c2i_entry() |
107 | // The entry point for calling both from and to compiled code is |
108 | // "_code->entry_point()". Because of tiered compilation and de-opt, this |
109 | // field can come and go. It can transition from NULL to not-null at any |
110 | // time (whenever a compile completes). It can transition from not-null to |
111 | // NULL only at safepoints (because of a de-opt). |
112 | CompiledMethod* volatile _code; // Points to the corresponding piece of native code |
113 | volatile address _from_interpreted_entry; // Cache of _code ? _adapter->i2c_entry() : _i2i_entry |
114 | |
115 | // Constructor |
116 | Method(ConstMethod* xconst, AccessFlags access_flags); |
117 | public: |
118 | |
119 | static Method* allocate(ClassLoaderData* loader_data, |
120 | int byte_code_size, |
121 | AccessFlags access_flags, |
122 | InlineTableSizes* sizes, |
123 | ConstMethod::MethodType method_type, |
124 | TRAPSJavaThread* __the_thread__); |
125 | |
126 | // CDS and vtbl checking can create an empty Method to get vtbl pointer. |
127 | Method(){} |
128 | |
129 | virtual bool is_method() const { return true; } |
130 | |
131 | void restore_unshareable_info(TRAPSJavaThread* __the_thread__); |
132 | |
133 | // accessors for instance variables |
134 | |
135 | ConstMethod* constMethod() const { return _constMethod; } |
136 | void set_constMethod(ConstMethod* xconst) { _constMethod = xconst; } |
137 | |
138 | |
139 | static address make_adapters(const methodHandle& mh, TRAPSJavaThread* __the_thread__); |
140 | address from_compiled_entry() const; |
141 | address from_compiled_entry_no_trampoline() const; |
142 | address from_interpreted_entry() const; |
143 | |
144 | // access flag |
145 | AccessFlags access_flags() const { return _access_flags; } |
146 | void set_access_flags(AccessFlags flags) { _access_flags = flags; } |
147 | |
148 | // name |
149 | Symbol* name() const { return constants()->symbol_at(name_index()); } |
150 | int name_index() const { return constMethod()->name_index(); } |
151 | void set_name_index(int index) { constMethod()->set_name_index(index); } |
152 | |
153 | // signature |
154 | Symbol* signature() const { return constants()->symbol_at(signature_index()); } |
155 | int signature_index() const { return constMethod()->signature_index(); } |
156 | void set_signature_index(int index) { constMethod()->set_signature_index(index); } |
157 | |
158 | // generics support |
159 | Symbol* generic_signature() const { int idx = generic_signature_index(); return ((idx != 0) ? constants()->symbol_at(idx) : (Symbol*)NULL__null); } |
160 | int generic_signature_index() const { return constMethod()->generic_signature_index(); } |
161 | void set_generic_signature_index(int index) { constMethod()->set_generic_signature_index(index); } |
162 | |
163 | // annotations support |
164 | AnnotationArray* annotations() const { |
165 | return constMethod()->method_annotations(); |
166 | } |
167 | AnnotationArray* parameter_annotations() const { |
168 | return constMethod()->parameter_annotations(); |
169 | } |
170 | AnnotationArray* annotation_default() const { |
171 | return constMethod()->default_annotations(); |
172 | } |
173 | AnnotationArray* type_annotations() const { |
174 | return constMethod()->type_annotations(); |
175 | } |
176 | |
177 | // Helper routine: get klass name + "." + method name + signature as |
178 | // C string, for the purpose of providing more useful |
179 | // fatal error handling. The string is allocated in resource |
180 | // area if a buffer is not provided by the caller. |
181 | char* name_and_sig_as_C_string() const; |
182 | char* name_and_sig_as_C_string(char* buf, int size) const; |
183 | |
184 | // Static routine in the situations we don't have a Method* |
185 | static char* name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol* signature); |
186 | static char* name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol* signature, char* buf, int size); |
187 | |
188 | // Get return type + klass name + "." + method name + ( parameters types ) |
189 | // as a C string or print it to an outputStream. |
190 | // This is to be used to assemble strings passed to Java, so that |
191 | // the text more resembles Java code. Used in exception messages. |
192 | // Memory is allocated in the resource area; the caller needs |
193 | // a ResourceMark. |
194 | const char* external_name() const; |
195 | void print_external_name(outputStream *os) const; |
196 | |
197 | static const char* external_name( Klass* klass, Symbol* method_name, Symbol* signature); |
198 | static void print_external_name(outputStream *os, Klass* klass, Symbol* method_name, Symbol* signature); |
199 | |
200 | Bytecodes::Code java_code_at(int bci) const { |
201 | return Bytecodes::java_code_at(this, bcp_from(bci)); |
202 | } |
203 | Bytecodes::Code code_at(int bci) const { |
204 | return Bytecodes::code_at(this, bcp_from(bci)); |
205 | } |
206 | |
207 | // JVMTI breakpoints |
208 | #if !INCLUDE_JVMTI1 |
209 | Bytecodes::Code orig_bytecode_at(int bci) const { |
210 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/oops/method.hpp" , 210); ::breakpoint(); } while (0); |
211 | return Bytecodes::_shouldnotreachhere; |
212 | } |
213 | void set_orig_bytecode_at(int bci, Bytecodes::Code code) { |
214 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/oops/method.hpp" , 214); ::breakpoint(); } while (0); |
215 | }; |
216 | u2 number_of_breakpoints() const {return 0;} |
217 | #else // !INCLUDE_JVMTI |
218 | Bytecodes::Code orig_bytecode_at(int bci) const; |
219 | void set_orig_bytecode_at(int bci, Bytecodes::Code code); |
220 | void set_breakpoint(int bci); |
221 | void clear_breakpoint(int bci); |
222 | void clear_all_breakpoints(); |
223 | // Tracking number of breakpoints, for fullspeed debugging. |
224 | // Only mutated by VM thread. |
225 | u2 number_of_breakpoints() const { |
226 | MethodCounters* mcs = method_counters(); |
227 | if (mcs == NULL__null) { |
228 | return 0; |
229 | } else { |
230 | return mcs->number_of_breakpoints(); |
231 | } |
232 | } |
233 | void incr_number_of_breakpoints(Thread* current) { |
234 | MethodCounters* mcs = get_method_counters(current); |
235 | if (mcs != NULL__null) { |
236 | mcs->incr_number_of_breakpoints(); |
237 | } |
238 | } |
239 | void decr_number_of_breakpoints(Thread* current) { |
240 | MethodCounters* mcs = get_method_counters(current); |
241 | if (mcs != NULL__null) { |
242 | mcs->decr_number_of_breakpoints(); |
243 | } |
244 | } |
245 | // Initialization only |
246 | void clear_number_of_breakpoints() { |
247 | MethodCounters* mcs = method_counters(); |
248 | if (mcs != NULL__null) { |
249 | mcs->clear_number_of_breakpoints(); |
250 | } |
251 | } |
252 | #endif // !INCLUDE_JVMTI |
253 | |
254 | // index into InstanceKlass methods() array |
255 | // note: also used by jfr |
256 | u2 method_idnum() const { return constMethod()->method_idnum(); } |
257 | void set_method_idnum(u2 idnum) { constMethod()->set_method_idnum(idnum); } |
258 | |
259 | u2 orig_method_idnum() const { return constMethod()->orig_method_idnum(); } |
260 | void set_orig_method_idnum(u2 idnum) { constMethod()->set_orig_method_idnum(idnum); } |
261 | |
262 | // code size |
263 | int code_size() const { return constMethod()->code_size(); } |
264 | |
265 | // method size in words |
266 | int method_size() const { return sizeof(Method)/wordSize + ( is_native() ? 2 : 0 ); } |
267 | |
268 | // constant pool for Klass* holding this method |
269 | ConstantPool* constants() const { return constMethod()->constants(); } |
270 | void set_constants(ConstantPool* c) { constMethod()->set_constants(c); } |
271 | |
272 | // max stack |
273 | // return original max stack size for method verification |
274 | int verifier_max_stack() const { return constMethod()->max_stack(); } |
275 | int max_stack() const { return constMethod()->max_stack() + extra_stack_entries(); } |
276 | void set_max_stack(int size) { constMethod()->set_max_stack(size); } |
277 | |
278 | // max locals |
279 | int max_locals() const { return constMethod()->max_locals(); } |
280 | void set_max_locals(int size) { constMethod()->set_max_locals(size); } |
281 | |
282 | int highest_comp_level() const; |
283 | void set_highest_comp_level(int level); |
284 | int highest_osr_comp_level() const; |
285 | void set_highest_osr_comp_level(int level); |
286 | |
287 | #if COMPILER2_OR_JVMCI1 |
288 | // Count of times method was exited via exception while interpreting |
289 | void interpreter_throwout_increment(Thread* current) { |
290 | MethodCounters* mcs = get_method_counters(current); |
291 | if (mcs != NULL__null) { |
292 | mcs->interpreter_throwout_increment(); |
293 | } |
294 | } |
295 | #endif |
296 | |
297 | int interpreter_throwout_count() const { |
298 | MethodCounters* mcs = method_counters(); |
299 | if (mcs == NULL__null) { |
300 | return 0; |
301 | } else { |
302 | return mcs->interpreter_throwout_count(); |
303 | } |
304 | } |
305 | |
306 | // Derive stuff from the signature at load time. |
307 | void compute_from_signature(Symbol* sig); |
308 | |
309 | // size of parameters (receiver if any + arguments) |
310 | int size_of_parameters() const { return constMethod()->size_of_parameters(); } |
311 | void set_size_of_parameters(int size) { constMethod()->set_size_of_parameters(size); } |
312 | |
313 | bool has_stackmap_table() const { |
314 | return constMethod()->has_stackmap_table(); |
315 | } |
316 | |
317 | Array<u1>* stackmap_data() const { |
318 | return constMethod()->stackmap_data(); |
319 | } |
320 | |
321 | void set_stackmap_data(Array<u1>* sd) { |
322 | constMethod()->set_stackmap_data(sd); |
323 | } |
324 | |
325 | // exception handler table |
326 | bool has_exception_handler() const |
327 | { return constMethod()->has_exception_handler(); } |
328 | int exception_table_length() const |
329 | { return constMethod()->exception_table_length(); } |
330 | ExceptionTableElement* exception_table_start() const |
331 | { return constMethod()->exception_table_start(); } |
332 | |
333 | // Finds the first entry point bci of an exception handler for an |
334 | // exception of klass ex_klass thrown at throw_bci. A value of NULL |
335 | // for ex_klass indicates that the exception klass is not known; in |
336 | // this case it matches any constraint class. Returns -1 if the |
337 | // exception cannot be handled in this method. The handler |
338 | // constraint classes are loaded if necessary. Note that this may |
339 | // throw an exception if loading of the constraint classes causes |
340 | // an IllegalAccessError (bugid 4307310) or an OutOfMemoryError. |
341 | // If an exception is thrown, returns the bci of the |
342 | // exception handler which caused the exception to be thrown, which |
343 | // is needed for proper retries. See, for example, |
344 | // InterpreterRuntime::exception_handler_for_exception. |
345 | static int fast_exception_handler_bci_for(const methodHandle& mh, Klass* ex_klass, int throw_bci, TRAPSJavaThread* __the_thread__); |
346 | |
347 | static bool register_native(Klass* k, |
348 | Symbol* name, |
349 | Symbol* signature, |
350 | address entry, |
351 | TRAPSJavaThread* __the_thread__); |
352 | |
353 | // method data access |
354 | MethodData* method_data() const { |
355 | return _method_data; |
356 | } |
357 | |
358 | void set_method_data(MethodData* data); |
359 | |
360 | MethodCounters* method_counters() const { |
361 | return _method_counters; |
362 | } |
363 | |
364 | void clear_method_counters() { |
365 | _method_counters = NULL__null; |
366 | } |
367 | |
368 | bool init_method_counters(MethodCounters* counters); |
369 | |
370 | int prev_event_count() const { |
371 | MethodCounters* mcs = method_counters(); |
372 | return mcs == NULL__null ? 0 : mcs->prev_event_count(); |
373 | } |
374 | void set_prev_event_count(int count) { |
375 | MethodCounters* mcs = method_counters(); |
376 | if (mcs != NULL__null) { |
377 | mcs->set_prev_event_count(count); |
378 | } |
379 | } |
380 | jlong prev_time() const { |
381 | MethodCounters* mcs = method_counters(); |
382 | return mcs == NULL__null ? 0 : mcs->prev_time(); |
383 | } |
384 | void set_prev_time(jlong time) { |
385 | MethodCounters* mcs = method_counters(); |
386 | if (mcs != NULL__null) { |
387 | mcs->set_prev_time(time); |
388 | } |
389 | } |
390 | float rate() const { |
391 | MethodCounters* mcs = method_counters(); |
392 | return mcs == NULL__null ? 0 : mcs->rate(); |
393 | } |
394 | void set_rate(float rate) { |
395 | MethodCounters* mcs = method_counters(); |
396 | if (mcs != NULL__null) { |
397 | mcs->set_rate(rate); |
398 | } |
399 | } |
400 | |
401 | int nmethod_age() const { |
402 | if (method_counters() == NULL__null) { |
403 | return INT_MAX2147483647; |
404 | } else { |
405 | return method_counters()->nmethod_age(); |
406 | } |
407 | } |
408 | |
409 | int invocation_count() const; |
410 | int backedge_count() const; |
411 | |
412 | bool was_executed_more_than(int n); |
413 | bool was_never_executed() { return !was_executed_more_than(0); } |
414 | |
415 | static void build_interpreter_method_data(const methodHandle& method, TRAPSJavaThread* __the_thread__); |
416 | |
417 | static MethodCounters* build_method_counters(Thread* current, Method* m); |
418 | |
419 | int interpreter_invocation_count() { return invocation_count(); } |
420 | |
421 | #ifndef PRODUCT |
422 | int64_t compiled_invocation_count() const { return _compiled_invocation_count;} |
423 | void set_compiled_invocation_count(int count) { _compiled_invocation_count = (int64_t)count; } |
424 | #else |
425 | // for PrintMethodData in a product build |
426 | int64_t compiled_invocation_count() const { return 0; } |
427 | #endif // not PRODUCT |
428 | |
429 | // Clear (non-shared space) pointers which could not be relevant |
430 | // if this (shared) method were mapped into another JVM. |
431 | void remove_unshareable_info(); |
432 | |
433 | // nmethod/verified compiler entry |
434 | address verified_code_entry(); |
435 | bool check_code() const; // Not inline to avoid circular ref |
436 | CompiledMethod* volatile code() const; |
437 | |
438 | // Locks CompiledMethod_lock if not held. |
439 | void unlink_code(CompiledMethod *compare); |
440 | // Locks CompiledMethod_lock if not held. |
441 | void unlink_code(); |
442 | |
443 | private: |
444 | // Either called with CompiledMethod_lock held or from constructor. |
445 | void clear_code(); |
446 | |
447 | public: |
448 | static void set_code(const methodHandle& mh, CompiledMethod* code); |
449 | void set_adapter_entry(AdapterHandlerEntry* adapter) { |
450 | _adapter = adapter; |
451 | } |
452 | void set_from_compiled_entry(address entry) { |
453 | _from_compiled_entry = entry; |
454 | } |
455 | |
456 | address get_i2c_entry(); |
457 | address get_c2i_entry(); |
458 | address get_c2i_unverified_entry(); |
459 | address get_c2i_no_clinit_check_entry(); |
460 | AdapterHandlerEntry* adapter() const { |
461 | return _adapter; |
462 | } |
463 | // setup entry points |
464 | void link_method(const methodHandle& method, TRAPSJavaThread* __the_thread__); |
465 | // clear entry points. Used by sharing code during dump time |
466 | void unlink_method() NOT_CDS_RETURN; |
467 | |
468 | virtual void metaspace_pointers_do(MetaspaceClosure* iter); |
469 | virtual MetaspaceObj::Type type() const { return MethodType; } |
470 | |
471 | // vtable index |
472 | enum VtableIndexFlag { |
473 | // Valid vtable indexes are non-negative (>= 0). |
474 | // These few negative values are used as sentinels. |
475 | itable_index_max = -10, // first itable index, growing downward |
476 | pending_itable_index = -9, // itable index will be assigned |
477 | invalid_vtable_index = -4, // distinct from any valid vtable index |
478 | garbage_vtable_index = -3, // not yet linked; no vtable layout yet |
479 | nonvirtual_vtable_index = -2 // there is no need for vtable dispatch |
480 | // 6330203 Note: Do not use -1, which was overloaded with many meanings. |
481 | }; |
482 | DEBUG_ONLY(bool valid_vtable_index() const { return _vtable_index >= nonvirtual_vtable_index; })bool valid_vtable_index() const { return _vtable_index >= nonvirtual_vtable_index ; } |
483 | bool has_vtable_index() const { return _vtable_index >= 0; } |
484 | int vtable_index() const { return _vtable_index; } |
485 | void set_vtable_index(int index); |
486 | DEBUG_ONLY(bool valid_itable_index() const { return _vtable_index <= pending_itable_index; })bool valid_itable_index() const { return _vtable_index <= pending_itable_index ; } |
487 | bool has_itable_index() const { return _vtable_index <= itable_index_max; } |
488 | int itable_index() const { assert(valid_itable_index(), "")do { if (!(valid_itable_index())) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/method.hpp" , 488, "assert(" "valid_itable_index()" ") failed", ""); ::breakpoint (); } } while (0); |
489 | return itable_index_max - _vtable_index; } |
490 | void set_itable_index(int index); |
491 | |
492 | // interpreter entry |
493 | address interpreter_entry() const { return _i2i_entry; } |
494 | // Only used when first initialize so we can set _i2i_entry and _from_interpreted_entry |
495 | void set_interpreter_entry(address entry) { |
496 | if (_i2i_entry != entry) { |
497 | _i2i_entry = entry; |
498 | } |
499 | if (_from_interpreted_entry != entry) { |
500 | _from_interpreted_entry = entry; |
501 | } |
502 | } |
503 | |
504 | // native function (used for native methods only) |
505 | enum { |
506 | native_bind_event_is_interesting = true |
507 | }; |
508 | address native_function() const { return *(native_function_addr()); } |
509 | |
510 | // Must specify a real function (not NULL). |
511 | // Use clear_native_function() to unregister. |
512 | void set_native_function(address function, bool post_event_flag); |
513 | bool has_native_function() const; |
514 | void clear_native_function(); |
515 | |
516 | // signature handler (used for native methods only) |
517 | address signature_handler() const { return *(signature_handler_addr()); } |
518 | void set_signature_handler(address handler); |
519 | |
520 | // Interpreter oopmap support |
521 | void mask_for(int bci, InterpreterOopMap* mask); |
522 | |
523 | // operations on invocation counter |
524 | void print_invocation_count(); |
525 | |
526 | // byte codes |
527 | void set_code(address code) { return constMethod()->set_code(code); } |
528 | address code_base() const { return constMethod()->code_base(); } |
529 | bool contains(address bcp) const { return constMethod()->contains(bcp); } |
530 | |
531 | // prints byte codes |
532 | void print_codes() const { print_codes_on(tty); } |
533 | void print_codes_on(outputStream* st) const; |
534 | void print_codes_on(int from, int to, outputStream* st) const; |
535 | |
536 | // method parameters |
537 | bool has_method_parameters() const |
538 | { return constMethod()->has_method_parameters(); } |
539 | int method_parameters_length() const |
540 | { return constMethod()->method_parameters_length(); } |
541 | MethodParametersElement* method_parameters_start() const |
542 | { return constMethod()->method_parameters_start(); } |
543 | |
544 | // checked exceptions |
545 | int checked_exceptions_length() const |
546 | { return constMethod()->checked_exceptions_length(); } |
547 | CheckedExceptionElement* checked_exceptions_start() const |
548 | { return constMethod()->checked_exceptions_start(); } |
549 | |
550 | // localvariable table |
551 | bool has_localvariable_table() const |
552 | { return constMethod()->has_localvariable_table(); } |
553 | int localvariable_table_length() const |
554 | { return constMethod()->localvariable_table_length(); } |
555 | LocalVariableTableElement* localvariable_table_start() const |
556 | { return constMethod()->localvariable_table_start(); } |
557 | |
558 | bool has_linenumber_table() const |
559 | { return constMethod()->has_linenumber_table(); } |
560 | u_char* compressed_linenumber_table() const |
561 | { return constMethod()->compressed_linenumber_table(); } |
562 | |
563 | // method holder (the Klass* holding this method) |
564 | InstanceKlass* method_holder() const { return constants()->pool_holder(); } |
565 | |
566 | Symbol* klass_name() const; // returns the name of the method holder |
567 | BasicType result_type() const { return constMethod()->result_type(); } |
568 | bool is_returning_oop() const { BasicType r = result_type(); return is_reference_type(r); } |
569 | bool is_returning_fp() const { BasicType r = result_type(); return (r == T_FLOAT || r == T_DOUBLE); } |
570 | |
571 | // Checked exceptions thrown by this method (resolved to mirrors) |
572 | objArrayHandle resolved_checked_exceptions(TRAPSJavaThread* __the_thread__) { return resolved_checked_exceptions_impl(this, THREAD__the_thread__); } |
573 | |
574 | // Access flags |
575 | bool is_public() const { return access_flags().is_public(); } |
576 | bool is_private() const { return access_flags().is_private(); } |
577 | bool is_protected() const { return access_flags().is_protected(); } |
578 | bool is_package_private() const { return !is_public() && !is_private() && !is_protected(); } |
579 | bool is_static() const { return access_flags().is_static(); } |
580 | bool is_final() const { return access_flags().is_final(); } |
581 | bool is_synchronized() const { return access_flags().is_synchronized();} |
582 | bool is_native() const { return access_flags().is_native(); } |
583 | bool is_abstract() const { return access_flags().is_abstract(); } |
584 | bool is_synthetic() const { return access_flags().is_synthetic(); } |
585 | |
586 | // returns true if contains only return operation |
587 | bool is_empty_method() const; |
588 | |
589 | // returns true if this is a vanilla constructor |
590 | bool is_vanilla_constructor() const; |
591 | |
592 | // checks method and its method holder |
593 | bool is_final_method() const; |
594 | bool is_final_method(AccessFlags class_access_flags) const; |
595 | // interface method declared with 'default' - excludes private interface methods |
596 | bool is_default_method() const; |
597 | |
598 | // true if method needs no dynamic dispatch (final and/or no vtable entry) |
599 | bool can_be_statically_bound() const; |
600 | bool can_be_statically_bound(InstanceKlass* context) const; |
601 | bool can_be_statically_bound(AccessFlags class_access_flags) const; |
602 | |
603 | // true if method can omit stack trace in throw in compiled code. |
604 | bool can_omit_stack_trace(); |
605 | |
606 | // returns true if the method has any backward branches. |
607 | bool has_loops() { |
608 | return access_flags().loops_flag_init() ? access_flags().has_loops() : compute_has_loops_flag(); |
609 | }; |
610 | |
611 | bool compute_has_loops_flag(); |
612 | |
613 | bool has_jsrs() { |
614 | return access_flags().has_jsrs(); |
615 | }; |
616 | void set_has_jsrs() { |
617 | _access_flags.set_has_jsrs(); |
618 | } |
619 | |
620 | // returns true if the method has any monitors. |
621 | bool has_monitors() const { return is_synchronized() || access_flags().has_monitor_bytecodes(); } |
622 | bool has_monitor_bytecodes() const { return access_flags().has_monitor_bytecodes(); } |
623 | |
624 | void set_has_monitor_bytecodes() { _access_flags.set_has_monitor_bytecodes(); } |
625 | |
626 | // monitor matching. This returns a conservative estimate of whether the monitorenter/monitorexit bytecodes |
627 | // propererly nest in the method. It might return false, even though they actually nest properly, since the info. |
628 | // has not been computed yet. |
629 | bool guaranteed_monitor_matching() const { return access_flags().is_monitor_matching(); } |
630 | void set_guaranteed_monitor_matching() { _access_flags.set_monitor_matching(); } |
631 | |
632 | // returns true if the method is an accessor function (setter/getter). |
633 | bool is_accessor() const; |
634 | |
635 | // returns true if the method is a getter |
636 | bool is_getter() const; |
637 | |
638 | // returns true if the method is a setter |
639 | bool is_setter() const; |
640 | |
641 | // returns true if the method does nothing but return a constant of primitive type |
642 | bool is_constant_getter() const; |
643 | |
644 | // returns true if the method is an initializer (<init> or <clinit>). |
645 | bool is_initializer() const; |
646 | |
647 | // returns true if the method is static OR if the classfile version < 51 |
648 | bool has_valid_initializer_flags() const; |
649 | |
650 | // returns true if the method name is <clinit> and the method has |
651 | // valid static initializer flags. |
652 | bool is_static_initializer() const; |
653 | |
654 | // returns true if the method name is <init> |
655 | bool is_object_initializer() const; |
656 | |
657 | // compiled code support |
658 | // NOTE: code() is inherently racy as deopt can be clearing code |
659 | // simultaneously. Use with caution. |
660 | bool has_compiled_code() const; |
661 | |
662 | bool needs_clinit_barrier() const; |
663 | |
664 | // sizing |
665 | static int header_size() { |
666 | return align_up((int)sizeof(Method), wordSize) / wordSize; |
667 | } |
668 | static int size(bool is_native); |
669 | int size() const { return method_size(); } |
670 | void log_touched(Thread* current); |
671 | static void print_touched_methods(outputStream* out); |
672 | |
673 | // interpreter support |
674 | static ByteSize const_offset() { return byte_offset_of(Method, _constMethod )in_ByteSize((int)(size_t)((intx)&(((Method*)16)->_constMethod ) - 16)); } |
675 | static ByteSize access_flags_offset() { return byte_offset_of(Method, _access_flags )in_ByteSize((int)(size_t)((intx)&(((Method*)16)->_access_flags ) - 16)); } |
676 | static ByteSize from_compiled_offset() { return byte_offset_of(Method, _from_compiled_entry)in_ByteSize((int)(size_t)((intx)&(((Method*)16)->_from_compiled_entry ) - 16)); } |
677 | static ByteSize code_offset() { return byte_offset_of(Method, _code)in_ByteSize((int)(size_t)((intx)&(((Method*)16)->_code ) - 16)); } |
678 | static ByteSize method_data_offset() { |
679 | return byte_offset_of(Method, _method_data)in_ByteSize((int)(size_t)((intx)&(((Method*)16)->_method_data ) - 16)); |
680 | } |
681 | static ByteSize method_counters_offset() { |
682 | return byte_offset_of(Method, _method_counters)in_ByteSize((int)(size_t)((intx)&(((Method*)16)->_method_counters ) - 16)); |
683 | } |
684 | #ifndef PRODUCT |
685 | static ByteSize compiled_invocation_counter_offset() { return byte_offset_of(Method, _compiled_invocation_count)in_ByteSize((int)(size_t)((intx)&(((Method*)16)->_compiled_invocation_count ) - 16)); } |
686 | #endif // not PRODUCT |
687 | static ByteSize native_function_offset() { return in_ByteSize(sizeof(Method)); } |
688 | static ByteSize from_interpreted_offset() { return byte_offset_of(Method, _from_interpreted_entry )in_ByteSize((int)(size_t)((intx)&(((Method*)16)->_from_interpreted_entry ) - 16)); } |
689 | static ByteSize interpreter_entry_offset() { return byte_offset_of(Method, _i2i_entry )in_ByteSize((int)(size_t)((intx)&(((Method*)16)->_i2i_entry ) - 16)); } |
690 | static ByteSize signature_handler_offset() { return in_ByteSize(sizeof(Method) + wordSize); } |
691 | static ByteSize itable_index_offset() { return byte_offset_of(Method, _vtable_index )in_ByteSize((int)(size_t)((intx)&(((Method*)16)->_vtable_index ) - 16)); } |
692 | |
693 | // for code generation |
694 | static int method_data_offset_in_bytes() { return offset_of(Method, _method_data)(size_t)((intx)&(((Method*)16)->_method_data) - 16); } |
695 | static int intrinsic_id_offset_in_bytes() { return offset_of(Method, _intrinsic_id)(size_t)((intx)&(((Method*)16)->_intrinsic_id) - 16); } |
696 | static int intrinsic_id_size_in_bytes() { return sizeof(u2); } |
697 | |
698 | // Static methods that are used to implement member methods where an exposed this pointer |
699 | // is needed due to possible GCs |
700 | static objArrayHandle resolved_checked_exceptions_impl(Method* method, TRAPSJavaThread* __the_thread__); |
701 | |
702 | // Returns the byte code index from the byte code pointer |
703 | int bci_from(address bcp) const; |
704 | address bcp_from(int bci) const; |
705 | address bcp_from(address bcp) const; |
706 | int validate_bci_from_bcp(address bcp) const; |
707 | int validate_bci(int bci) const; |
708 | |
709 | // Returns the line number for a bci if debugging information for the method is prowided, |
710 | // -1 is returned otherwise. |
711 | int line_number_from_bci(int bci) const; |
712 | |
713 | // Reflection support |
714 | bool is_overridden_in(Klass* k) const; |
715 | |
716 | // Stack walking support |
717 | bool is_ignored_by_security_stack_walk() const; |
718 | |
719 | // JSR 292 support |
720 | bool is_method_handle_intrinsic() const; // MethodHandles::is_signature_polymorphic_intrinsic(intrinsic_id) |
721 | bool is_compiled_lambda_form() const; // intrinsic_id() == vmIntrinsics::_compiledLambdaForm |
722 | bool has_member_arg() const; // intrinsic_id() == vmIntrinsics::_linkToSpecial, etc. |
723 | static methodHandle make_method_handle_intrinsic(vmIntrinsicID iid, // _invokeBasic, _linkToVirtual |
724 | Symbol* signature, //anything at all |
725 | TRAPSJavaThread* __the_thread__); |
726 | static Klass* check_non_bcp_klass(Klass* klass); |
727 | |
728 | enum { |
729 | // How many extra stack entries for invokedynamic |
730 | extra_stack_entries_for_jsr292 = 1 |
731 | }; |
732 | |
733 | // this operates only on invoke methods: |
734 | // presize interpreter frames for extra interpreter stack entries, if needed |
735 | // Account for the extra appendix argument for invokehandle/invokedynamic |
736 | static int extra_stack_entries() { return extra_stack_entries_for_jsr292; } |
737 | static int extra_stack_words(); // = extra_stack_entries() * Interpreter::stackElementSize |
738 | |
739 | // RedefineClasses() support: |
740 | bool is_old() const { return access_flags().is_old(); } |
741 | void set_is_old() { _access_flags.set_is_old(); } |
742 | bool is_obsolete() const { return access_flags().is_obsolete(); } |
743 | void set_is_obsolete() { _access_flags.set_is_obsolete(); } |
744 | bool is_deleted() const { return access_flags().is_deleted(); } |
745 | void set_is_deleted() { _access_flags.set_is_deleted(); } |
746 | |
747 | bool on_stack() const { return access_flags().on_stack(); } |
748 | void set_on_stack(const bool value); |
749 | |
750 | // see the definition in Method*.cpp for the gory details |
751 | bool should_not_be_cached() const; |
752 | |
753 | // JVMTI Native method prefixing support: |
754 | bool is_prefixed_native() const { return access_flags().is_prefixed_native(); } |
755 | void set_is_prefixed_native() { _access_flags.set_is_prefixed_native(); } |
756 | |
757 | // Rewriting support |
758 | static methodHandle clone_with_new_data(const methodHandle& m, u_char* new_code, int new_code_length, |
759 | u_char* new_compressed_linenumber_table, int new_compressed_linenumber_size, TRAPSJavaThread* __the_thread__); |
760 | |
761 | // jmethodID handling |
762 | // Because the useful life-span of a jmethodID cannot be determined, |
763 | // once created they are never reclaimed. The methods to which they refer, |
764 | // however, can be GC'ed away if the class is unloaded or if the method is |
765 | // made obsolete or deleted -- in these cases, the jmethodID |
766 | // refers to NULL (as is the case for any weak reference). |
767 | static jmethodID make_jmethod_id(ClassLoaderData* loader_data, Method* mh); |
768 | static void destroy_jmethod_id(ClassLoaderData* loader_data, jmethodID mid); |
769 | |
770 | // Ensure there is enough capacity in the internal tracking data |
771 | // structures to hold the number of jmethodIDs you plan to generate. |
772 | // This saves substantial time doing allocations. |
773 | static void ensure_jmethod_ids(ClassLoaderData* loader_data, int capacity); |
774 | |
775 | // Use resolve_jmethod_id() in situations where the caller is expected |
776 | // to provide a valid jmethodID; the only sanity checks are in asserts; |
777 | // result guaranteed not to be NULL. |
778 | inline static Method* resolve_jmethod_id(jmethodID mid) { |
779 | assert(mid != NULL, "JNI method id should not be null")do { if (!(mid != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/method.hpp" , 779, "assert(" "mid != __null" ") failed", "JNI method id should not be null" ); ::breakpoint(); } } while (0); |
780 | return *((Method**)mid); |
781 | } |
782 | |
783 | // Use checked_resolve_jmethod_id() in situations where the caller |
784 | // should provide a valid jmethodID, but might not. NULL is returned |
785 | // when the jmethodID does not refer to a valid method. |
786 | static Method* checked_resolve_jmethod_id(jmethodID mid); |
787 | |
788 | static void change_method_associated_with_jmethod_id(jmethodID old_jmid_ptr, Method* new_method); |
789 | static bool is_method_id(jmethodID mid); |
790 | |
791 | // Clear methods |
792 | static void clear_jmethod_ids(ClassLoaderData* loader_data); |
793 | static void print_jmethod_ids_count(const ClassLoaderData* loader_data, outputStream* out) PRODUCT_RETURN; |
794 | |
795 | // Get this method's jmethodID -- allocate if it doesn't exist |
796 | jmethodID jmethod_id(); |
797 | |
798 | // Lookup the jmethodID for this method. Return NULL if not found. |
799 | // NOTE that this function can be called from a signal handler |
800 | // (see AsyncGetCallTrace support for Forte Analyzer) and this |
801 | // needs to be async-safe. No allocation should be done and |
802 | // so handles are not used to avoid deadlock. |
803 | jmethodID find_jmethod_id_or_null() { return method_holder()->jmethod_id_or_null(this); } |
804 | |
805 | // Support for inlining of intrinsic methods |
806 | vmIntrinsicID intrinsic_id() const { return (vmIntrinsicID) _intrinsic_id; } |
807 | void set_intrinsic_id(vmIntrinsicID id) { _intrinsic_id = (u2) id; } |
808 | |
809 | // Helper routines for intrinsic_id() and vmIntrinsics::method(). |
810 | void init_intrinsic_id(vmSymbolID klass_id); // updates from _none if a match |
811 | static vmSymbolID klass_id_for_intrinsics(const Klass* holder); |
812 | |
813 | bool caller_sensitive() { |
814 | return (_flags & _caller_sensitive) != 0; |
815 | } |
816 | void set_caller_sensitive(bool x) { |
817 | _flags = x ? (_flags | _caller_sensitive) : (_flags & ~_caller_sensitive); |
818 | } |
819 | |
820 | bool force_inline() { |
821 | return (_flags & _force_inline) != 0; |
822 | } |
823 | void set_force_inline(bool x) { |
824 | _flags = x ? (_flags | _force_inline) : (_flags & ~_force_inline); |
825 | } |
826 | |
827 | bool dont_inline() { |
828 | return (_flags & _dont_inline) != 0; |
829 | } |
830 | void set_dont_inline(bool x) { |
831 | _flags = x ? (_flags | _dont_inline) : (_flags & ~_dont_inline); |
832 | } |
833 | |
834 | bool is_hidden() const { |
835 | return (_flags & _hidden) != 0; |
836 | } |
837 | |
838 | void set_hidden(bool x) { |
839 | _flags = x ? (_flags | _hidden) : (_flags & ~_hidden); |
840 | } |
841 | |
842 | bool is_scoped() const { |
843 | return (_flags & _scoped) != 0; |
844 | } |
845 | |
846 | void set_scoped(bool x) { |
847 | _flags = x ? (_flags | _scoped) : (_flags & ~_scoped); |
848 | } |
849 | |
850 | bool intrinsic_candidate() { |
851 | return (_flags & _intrinsic_candidate) != 0; |
852 | } |
853 | void set_intrinsic_candidate(bool x) { |
854 | _flags = x ? (_flags | _intrinsic_candidate) : (_flags & ~_intrinsic_candidate); |
855 | } |
856 | |
857 | bool has_injected_profile() { |
858 | return (_flags & _has_injected_profile) != 0; |
859 | } |
860 | void set_has_injected_profile(bool x) { |
861 | _flags = x ? (_flags | _has_injected_profile) : (_flags & ~_has_injected_profile); |
862 | } |
863 | |
864 | bool has_reserved_stack_access() { |
865 | return (_flags & _reserved_stack_access) != 0; |
866 | } |
867 | |
868 | void set_has_reserved_stack_access(bool x) { |
869 | _flags = x ? (_flags | _reserved_stack_access) : (_flags & ~_reserved_stack_access); |
870 | } |
871 | |
872 | JFR_ONLY(DEFINE_TRACE_FLAG_ACCESSOR;)bool is_trace_flag_set(jshort flag) const { return _trace_flags .is_set(flag); } jshort trace_flags() const { return _trace_flags .flags(); } void set_trace_flags(jshort flags) const { _trace_flags .set_flags(flags); } jbyte* trace_flags_addr() const { return _trace_flags.flags_addr(); } jbyte* trace_meta_addr() const { return _trace_flags.meta_addr(); }; |
873 | |
874 | ConstMethod::MethodType method_type() const { |
875 | return _constMethod->method_type(); |
876 | } |
877 | bool is_overpass() const { return method_type() == ConstMethod::OVERPASS; } |
878 | |
879 | // On-stack replacement support |
880 | bool has_osr_nmethod(int level, bool match_level) { |
881 | return method_holder()->lookup_osr_nmethod(this, InvocationEntryBci, level, match_level) != NULL__null; |
882 | } |
883 | |
884 | int mark_osr_nmethods() { |
885 | return method_holder()->mark_osr_nmethods(this); |
886 | } |
887 | |
888 | nmethod* lookup_osr_nmethod_for(int bci, int level, bool match_level) { |
889 | return method_holder()->lookup_osr_nmethod(this, bci, level, match_level); |
890 | } |
891 | |
892 | // Find if klass for method is loaded |
893 | bool is_klass_loaded_by_klass_index(int klass_index) const; |
894 | bool is_klass_loaded(int refinfo_index, bool must_be_resolved = false) const; |
895 | |
896 | // Indicates whether compilation failed earlier for this method, or |
897 | // whether it is not compilable for another reason like having a |
898 | // breakpoint set in it. |
899 | bool is_not_compilable(int comp_level = CompLevel_any) const; |
900 | void set_not_compilable(const char* reason, int comp_level = CompLevel_all, bool report = true); |
901 | void set_not_compilable_quietly(const char* reason, int comp_level = CompLevel_all) { |
902 | set_not_compilable(reason, comp_level, false); |
903 | } |
904 | bool is_not_osr_compilable(int comp_level = CompLevel_any) const; |
905 | void set_not_osr_compilable(const char* reason, int comp_level = CompLevel_all, bool report = true); |
906 | void set_not_osr_compilable_quietly(const char* reason, int comp_level = CompLevel_all) { |
907 | set_not_osr_compilable(reason, comp_level, false); |
908 | } |
909 | bool is_always_compilable() const; |
910 | |
911 | private: |
912 | void print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason); |
913 | |
914 | public: |
915 | MethodCounters* get_method_counters(Thread* current) { |
916 | if (_method_counters == NULL__null) { |
917 | build_method_counters(current, this); |
918 | } |
919 | return _method_counters; |
920 | } |
921 | |
922 | bool is_not_c1_compilable() const { return access_flags().is_not_c1_compilable(); } |
923 | void set_not_c1_compilable() { _access_flags.set_not_c1_compilable(); } |
924 | void clear_not_c1_compilable() { _access_flags.clear_not_c1_compilable(); } |
925 | bool is_not_c2_compilable() const { return access_flags().is_not_c2_compilable(); } |
926 | void set_not_c2_compilable() { _access_flags.set_not_c2_compilable(); } |
927 | void clear_not_c2_compilable() { _access_flags.clear_not_c2_compilable(); } |
928 | |
929 | bool is_not_c1_osr_compilable() const { return is_not_c1_compilable(); } // don't waste an accessFlags bit |
930 | void set_not_c1_osr_compilable() { set_not_c1_compilable(); } // don't waste an accessFlags bit |
931 | void clear_not_c1_osr_compilable() { clear_not_c1_compilable(); } // don't waste an accessFlags bit |
932 | bool is_not_c2_osr_compilable() const { return access_flags().is_not_c2_osr_compilable(); } |
933 | void set_not_c2_osr_compilable() { _access_flags.set_not_c2_osr_compilable(); } |
934 | void clear_not_c2_osr_compilable() { _access_flags.clear_not_c2_osr_compilable(); } |
935 | |
936 | // Background compilation support |
937 | bool queued_for_compilation() const { return access_flags().queued_for_compilation(); } |
938 | void set_queued_for_compilation() { _access_flags.set_queued_for_compilation(); } |
939 | void clear_queued_for_compilation() { _access_flags.clear_queued_for_compilation(); } |
940 | |
941 | // Resolve all classes in signature, return 'true' if successful |
942 | static bool load_signature_classes(const methodHandle& m, TRAPSJavaThread* __the_thread__); |
943 | |
944 | // Return if true if not all classes references in signature, including return type, has been loaded |
945 | static bool has_unloaded_classes_in_signature(const methodHandle& m, TRAPSJavaThread* __the_thread__); |
946 | |
947 | // Printing |
948 | void print_short_name(outputStream* st = tty); // prints as klassname::methodname; Exposed so field engineers can debug VM |
949 | #if INCLUDE_JVMTI1 |
950 | void print_name(outputStream* st = tty); // prints as "virtual void foo(int)"; exposed for -Xlog:redefine+class |
951 | #else |
952 | void print_name(outputStream* st = tty) PRODUCT_RETURN; // prints as "virtual void foo(int)" |
953 | #endif |
954 | |
955 | typedef int (*method_comparator_func)(Method* a, Method* b); |
956 | |
957 | // Helper routine used for method sorting |
958 | static void sort_methods(Array<Method*>* methods, bool set_idnums = true, method_comparator_func func = NULL__null); |
959 | |
960 | // Deallocation function for redefine classes or if an error occurs |
961 | void deallocate_contents(ClassLoaderData* loader_data); |
962 | |
963 | void release_C_heap_structures(); |
964 | |
965 | Method* get_new_method() const { |
966 | InstanceKlass* holder = method_holder(); |
967 | Method* new_method = holder->method_with_idnum(orig_method_idnum()); |
968 | |
969 | assert(new_method != NULL, "method_with_idnum() should not be NULL")do { if (!(new_method != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/method.hpp" , 969, "assert(" "new_method != __null" ") failed", "method_with_idnum() should not be NULL" ); ::breakpoint(); } } while (0); |
970 | assert(this != new_method, "sanity check")do { if (!(this != new_method)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/method.hpp" , 970, "assert(" "this != new_method" ") failed", "sanity check" ); ::breakpoint(); } } while (0); |
971 | return new_method; |
972 | } |
973 | |
974 | // Printing |
975 | #ifndef PRODUCT |
976 | void print_on(outputStream* st) const; |
977 | #endif |
978 | void print_value_on(outputStream* st) const; |
979 | void print_linkage_flags(outputStream* st) PRODUCT_RETURN; |
980 | |
981 | const char* internal_name() const { return "{method}"; } |
982 | |
983 | // Check for valid method pointer |
984 | static bool has_method_vptr(const void* ptr); |
985 | static bool is_valid_method(const Method* m); |
986 | |
987 | // Verify |
988 | void verify() { verify_on(tty); } |
989 | void verify_on(outputStream* st); |
990 | |
991 | private: |
992 | |
993 | // Inlined elements |
994 | address* native_function_addr() const { assert(is_native(), "must be native")do { if (!(is_native())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/method.hpp" , 994, "assert(" "is_native()" ") failed", "must be native"); ::breakpoint(); } } while (0); return (address*) (this+1); } |
995 | address* signature_handler_addr() const { return native_function_addr() + 1; } |
996 | }; |
997 | |
998 | |
999 | // Utility class for compressing line number tables |
1000 | |
1001 | class CompressedLineNumberWriteStream: public CompressedWriteStream { |
1002 | private: |
1003 | int _bci; |
1004 | int _line; |
1005 | public: |
1006 | // Constructor |
1007 | CompressedLineNumberWriteStream(int initial_size) : CompressedWriteStream(initial_size), _bci(0), _line(0) {} |
1008 | CompressedLineNumberWriteStream(u_char* buffer, int initial_size) : CompressedWriteStream(buffer, initial_size), _bci(0), _line(0) {} |
1009 | |
1010 | // Write (bci, line number) pair to stream |
1011 | void write_pair_regular(int bci_delta, int line_delta); |
1012 | |
1013 | // If (bci delta, line delta) fits in (5-bit unsigned, 3-bit unsigned) |
1014 | // we save it as one byte, otherwise we write a 0xFF escape character |
1015 | // and use regular compression. 0x0 is used as end-of-stream terminator. |
1016 | void write_pair_inline(int bci, int line); |
1017 | |
1018 | void write_pair(int bci, int line); |
1019 | |
1020 | // Write end-of-stream marker |
1021 | void write_terminator() { write_byte(0); } |
1022 | }; |
1023 | |
1024 | |
1025 | // Utility class for decompressing line number tables |
1026 | |
1027 | class CompressedLineNumberReadStream: public CompressedReadStream { |
1028 | private: |
1029 | int _bci; |
1030 | int _line; |
1031 | public: |
1032 | // Constructor |
1033 | CompressedLineNumberReadStream(u_char* buffer); |
1034 | // Read (bci, line number) pair from stream. Returns false at end-of-stream. |
1035 | bool read_pair(); |
1036 | // Accessing bci and line number (after calling read_pair) |
1037 | int bci() const { return _bci; } |
1038 | int line() const { return _line; } |
1039 | }; |
1040 | |
1041 | |
1042 | #if INCLUDE_JVMTI1 |
1043 | |
1044 | /// Fast Breakpoints. |
1045 | |
1046 | // If this structure gets more complicated (because bpts get numerous), |
1047 | // move it into its own header. |
1048 | |
1049 | // There is presently no provision for concurrent access |
1050 | // to breakpoint lists, which is only OK for JVMTI because |
1051 | // breakpoints are written only at safepoints, and are read |
1052 | // concurrently only outside of safepoints. |
1053 | |
1054 | class BreakpointInfo : public CHeapObj<mtClass> { |
1055 | friend class VMStructs; |
1056 | private: |
1057 | Bytecodes::Code _orig_bytecode; |
1058 | int _bci; |
1059 | u2 _name_index; // of method |
1060 | u2 _signature_index; // of method |
1061 | BreakpointInfo* _next; // simple storage allocation |
1062 | |
1063 | public: |
1064 | BreakpointInfo(Method* m, int bci); |
1065 | |
1066 | // accessors |
1067 | Bytecodes::Code orig_bytecode() { return _orig_bytecode; } |
1068 | void set_orig_bytecode(Bytecodes::Code code) { _orig_bytecode = code; } |
1069 | int bci() { return _bci; } |
1070 | |
1071 | BreakpointInfo* next() const { return _next; } |
1072 | void set_next(BreakpointInfo* n) { _next = n; } |
1073 | |
1074 | // helps for searchers |
1075 | bool match(const Method* m, int bci) { |
1076 | return bci == _bci && match(m); |
1077 | } |
1078 | |
1079 | bool match(const Method* m) { |
1080 | return _name_index == m->name_index() && |
1081 | _signature_index == m->signature_index(); |
1082 | } |
1083 | |
1084 | void set(Method* method); |
1085 | void clear(Method* method); |
1086 | }; |
1087 | |
1088 | #endif // INCLUDE_JVMTI |
1089 | |
1090 | // Utility class for access exception handlers |
1091 | class ExceptionTable : public StackObj { |
1092 | private: |
1093 | ExceptionTableElement* _table; |
1094 | u2 _length; |
1095 | |
1096 | public: |
1097 | ExceptionTable(const Method* m) { |
1098 | if (m->has_exception_handler()) { |
1099 | _table = m->exception_table_start(); |
1100 | _length = m->exception_table_length(); |
1101 | } else { |
1102 | _table = NULL__null; |
1103 | _length = 0; |
1104 | } |
1105 | } |
1106 | |
1107 | int length() const { |
1108 | return _length; |
1109 | } |
1110 | |
1111 | u2 start_pc(int idx) const { |
1112 | assert(idx < _length, "out of bounds")do { if (!(idx < _length)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/method.hpp" , 1112, "assert(" "idx < _length" ") failed", "out of bounds" ); ::breakpoint(); } } while (0); |
1113 | return _table[idx].start_pc; |
1114 | } |
1115 | |
1116 | void set_start_pc(int idx, u2 value) { |
1117 | assert(idx < _length, "out of bounds")do { if (!(idx < _length)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/method.hpp" , 1117, "assert(" "idx < _length" ") failed", "out of bounds" ); ::breakpoint(); } } while (0); |
1118 | _table[idx].start_pc = value; |
1119 | } |
1120 | |
1121 | u2 end_pc(int idx) const { |
1122 | assert(idx < _length, "out of bounds")do { if (!(idx < _length)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/method.hpp" , 1122, "assert(" "idx < _length" ") failed", "out of bounds" ); ::breakpoint(); } } while (0); |
1123 | return _table[idx].end_pc; |
1124 | } |
1125 | |
1126 | void set_end_pc(int idx, u2 value) { |
1127 | assert(idx < _length, "out of bounds")do { if (!(idx < _length)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/method.hpp" , 1127, "assert(" "idx < _length" ") failed", "out of bounds" ); ::breakpoint(); } } while (0); |
1128 | _table[idx].end_pc = value; |
1129 | } |
1130 | |
1131 | u2 handler_pc(int idx) const { |
1132 | assert(idx < _length, "out of bounds")do { if (!(idx < _length)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/method.hpp" , 1132, "assert(" "idx < _length" ") failed", "out of bounds" ); ::breakpoint(); } } while (0); |
1133 | return _table[idx].handler_pc; |
1134 | } |
1135 | |
1136 | void set_handler_pc(int idx, u2 value) { |
1137 | assert(idx < _length, "out of bounds")do { if (!(idx < _length)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/method.hpp" , 1137, "assert(" "idx < _length" ") failed", "out of bounds" ); ::breakpoint(); } } while (0); |
1138 | _table[idx].handler_pc = value; |
1139 | } |
1140 | |
1141 | u2 catch_type_index(int idx) const { |
1142 | assert(idx < _length, "out of bounds")do { if (!(idx < _length)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/method.hpp" , 1142, "assert(" "idx < _length" ") failed", "out of bounds" ); ::breakpoint(); } } while (0); |
1143 | return _table[idx].catch_type_index; |
1144 | } |
1145 | |
1146 | void set_catch_type_index(int idx, u2 value) { |
1147 | assert(idx < _length, "out of bounds")do { if (!(idx < _length)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/method.hpp" , 1147, "assert(" "idx < _length" ") failed", "out of bounds" ); ::breakpoint(); } } while (0); |
1148 | _table[idx].catch_type_index = value; |
1149 | } |
1150 | }; |
1151 | |
1152 | #endif // SHARE_OOPS_METHOD_HPP |
1 | /* | |||
2 | * Copyright (c) 2003, 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 | #ifndef SHARE_OOPS_CONSTMETHOD_HPP | |||
26 | #define SHARE_OOPS_CONSTMETHOD_HPP | |||
27 | ||||
28 | #include "oops/oop.hpp" | |||
29 | #include "utilities/align.hpp" | |||
30 | ||||
31 | // An ConstMethod represents portions of a Java method which are not written to after | |||
32 | // the classfile is parsed(*see below). This part of the method can be shared across | |||
33 | // processes in a read-only section with Class Data Sharing (CDS). It's important | |||
34 | // that this class doesn't have virtual functions because the vptr cannot be shared | |||
35 | // with CDS. | |||
36 | // | |||
37 | // Note that most applications load thousands of methods, so keeping the size of this | |||
38 | // structure small has a big impact on footprint. | |||
39 | ||||
40 | // The actual bytecodes are inlined after the end of the ConstMethod struct. | |||
41 | // | |||
42 | // The line number table is compressed and inlined following the byte codes. It is | |||
43 | // found as the first byte following the byte codes. Note that accessing the line | |||
44 | // number and local variable tables is not performance critical at all. | |||
45 | // | |||
46 | // The checked exceptions table and the local variable table are inlined after the | |||
47 | // line number table, and indexed from the end of the method. We do not compress the | |||
48 | // checked exceptions table since the average length is less than 2, and it is used | |||
49 | // by reflection so access should be fast. We do not bother to compress the local | |||
50 | // variable table either since it is mostly absent. | |||
51 | // | |||
52 | // | |||
53 | // ConstMethod embedded field layout (after declared fields): | |||
54 | // [EMBEDDED byte codes] | |||
55 | // [EMBEDDED compressed linenumber table] | |||
56 | // (see class CompressedLineNumberReadStream) | |||
57 | // (note that length is unknown until decompressed) | |||
58 | // (access flags bit tells whether table is present) | |||
59 | // (indexed from start of ConstMethod) | |||
60 | // (elements not necessarily sorted!) | |||
61 | // [EMBEDDED localvariable table elements + length (length last)] | |||
62 | // (length is u2, elements are 6-tuples of u2) | |||
63 | // (see class LocalVariableTableElement) | |||
64 | // (access flags bit tells whether table is present) | |||
65 | // (indexed from end of ConstMethod*) | |||
66 | // [EMBEDDED exception table + length (length last)] | |||
67 | // (length is u2, elements are 4-tuples of u2) | |||
68 | // (see class ExceptionTableElement) | |||
69 | // (access flags bit tells whether table is present) | |||
70 | // (indexed from end of ConstMethod*) | |||
71 | // [EMBEDDED checked exceptions elements + length (length last)] | |||
72 | // (length is u2, elements are u2) | |||
73 | // (see class CheckedExceptionElement) | |||
74 | // (access flags bit tells whether table is present) | |||
75 | // (indexed from end of ConstMethod*) | |||
76 | // [EMBEDDED method parameters elements + length (length last)] | |||
77 | // (length is u2, elements are u2, u4 structures) | |||
78 | // (see class MethodParametersElement) | |||
79 | // (access flags bit tells whether table is present) | |||
80 | // (indexed from end of ConstMethod*) | |||
81 | // [EMBEDDED generic signature index (u2)] | |||
82 | // (indexed from end of constMethodOop) | |||
83 | // [EMBEDDED annotations arrays - method, parameter, type, default] | |||
84 | // pointer to Array<u1> if annotation is present | |||
85 | // | |||
86 | // IMPORTANT: If anything gets added here, there need to be changes to | |||
87 | // ensure that ServicabilityAgent doesn't get broken as a result! | |||
88 | ||||
89 | ||||
90 | // Utility class describing elements in checked exceptions table inlined in Method*. | |||
91 | class CheckedExceptionElement { | |||
92 | public: | |||
93 | u2 class_cp_index; | |||
94 | }; | |||
95 | ||||
96 | ||||
97 | // Utility class describing elements in local variable table inlined in Method*. | |||
98 | class LocalVariableTableElement { | |||
99 | public: | |||
100 | u2 start_bci; | |||
101 | u2 length; | |||
102 | u2 name_cp_index; | |||
103 | u2 descriptor_cp_index; | |||
104 | u2 signature_cp_index; | |||
105 | u2 slot; | |||
106 | }; | |||
107 | ||||
108 | // Utility class describing elements in exception table | |||
109 | class ExceptionTableElement { | |||
110 | public: | |||
111 | u2 start_pc; | |||
112 | u2 end_pc; | |||
113 | u2 handler_pc; | |||
114 | u2 catch_type_index; | |||
115 | }; | |||
116 | ||||
117 | // Utility class describing elements in method parameters | |||
118 | class MethodParametersElement { | |||
119 | public: | |||
120 | u2 name_cp_index; | |||
121 | u2 flags; | |||
122 | }; | |||
123 | ||||
124 | // Class to collect the sizes of ConstMethod inline tables | |||
125 | #define INLINE_TABLES_DO(do_element)do_element(localvariable_table_length) do_element(compressed_linenumber_size ) do_element(exception_table_length) do_element(checked_exceptions_length ) do_element(method_parameters_length) do_element(generic_signature_index ) do_element(method_annotations_length) do_element(parameter_annotations_length ) do_element(type_annotations_length) do_element(default_annotations_length ) \ | |||
126 | do_element(localvariable_table_length) \ | |||
127 | do_element(compressed_linenumber_size) \ | |||
128 | do_element(exception_table_length) \ | |||
129 | do_element(checked_exceptions_length) \ | |||
130 | do_element(method_parameters_length) \ | |||
131 | do_element(generic_signature_index) \ | |||
132 | do_element(method_annotations_length) \ | |||
133 | do_element(parameter_annotations_length) \ | |||
134 | do_element(type_annotations_length) \ | |||
135 | do_element(default_annotations_length) | |||
136 | ||||
137 | #define INLINE_TABLE_DECLARE(sym) int _##sym; | |||
138 | #define INLINE_TABLE_PARAM(sym) int sym, | |||
139 | #define INLINE_TABLE_INIT(sym) _##sym(sym), | |||
140 | #define INLINE_TABLE_NULL(sym) _##sym(0), | |||
141 | #define INLINE_TABLE_ACCESSOR(sym) int sym() const { return _##sym; } | |||
142 | ||||
143 | class InlineTableSizes : StackObj { | |||
144 | // declarations | |||
145 | INLINE_TABLES_DO(INLINE_TABLE_DECLARE)INLINE_TABLE_DECLARE(localvariable_table_length) INLINE_TABLE_DECLARE (compressed_linenumber_size) INLINE_TABLE_DECLARE(exception_table_length ) INLINE_TABLE_DECLARE(checked_exceptions_length) INLINE_TABLE_DECLARE (method_parameters_length) INLINE_TABLE_DECLARE(generic_signature_index ) INLINE_TABLE_DECLARE(method_annotations_length) INLINE_TABLE_DECLARE (parameter_annotations_length) INLINE_TABLE_DECLARE(type_annotations_length ) INLINE_TABLE_DECLARE(default_annotations_length) | |||
146 | int _end; | |||
147 | public: | |||
148 | InlineTableSizes( | |||
149 | INLINE_TABLES_DO(INLINE_TABLE_PARAM)INLINE_TABLE_PARAM(localvariable_table_length) INLINE_TABLE_PARAM (compressed_linenumber_size) INLINE_TABLE_PARAM(exception_table_length ) INLINE_TABLE_PARAM(checked_exceptions_length) INLINE_TABLE_PARAM (method_parameters_length) INLINE_TABLE_PARAM(generic_signature_index ) INLINE_TABLE_PARAM(method_annotations_length) INLINE_TABLE_PARAM (parameter_annotations_length) INLINE_TABLE_PARAM(type_annotations_length ) INLINE_TABLE_PARAM(default_annotations_length) | |||
150 | int end) : | |||
151 | INLINE_TABLES_DO(INLINE_TABLE_INIT)INLINE_TABLE_INIT(localvariable_table_length) INLINE_TABLE_INIT (compressed_linenumber_size) INLINE_TABLE_INIT(exception_table_length ) INLINE_TABLE_INIT(checked_exceptions_length) INLINE_TABLE_INIT (method_parameters_length) INLINE_TABLE_INIT(generic_signature_index ) INLINE_TABLE_INIT(method_annotations_length) INLINE_TABLE_INIT (parameter_annotations_length) INLINE_TABLE_INIT(type_annotations_length ) INLINE_TABLE_INIT(default_annotations_length) | |||
152 | _end(end) {} | |||
153 | ||||
154 | // Default constructor for no inlined tables | |||
155 | InlineTableSizes() : | |||
156 | INLINE_TABLES_DO(INLINE_TABLE_NULL)INLINE_TABLE_NULL(localvariable_table_length) INLINE_TABLE_NULL (compressed_linenumber_size) INLINE_TABLE_NULL(exception_table_length ) INLINE_TABLE_NULL(checked_exceptions_length) INLINE_TABLE_NULL (method_parameters_length) INLINE_TABLE_NULL(generic_signature_index ) INLINE_TABLE_NULL(method_annotations_length) INLINE_TABLE_NULL (parameter_annotations_length) INLINE_TABLE_NULL(type_annotations_length ) INLINE_TABLE_NULL(default_annotations_length) | |||
157 | _end(0) {} | |||
158 | ||||
159 | // Accessors | |||
160 | INLINE_TABLES_DO(INLINE_TABLE_ACCESSOR)INLINE_TABLE_ACCESSOR(localvariable_table_length) INLINE_TABLE_ACCESSOR (compressed_linenumber_size) INLINE_TABLE_ACCESSOR(exception_table_length ) INLINE_TABLE_ACCESSOR(checked_exceptions_length) INLINE_TABLE_ACCESSOR (method_parameters_length) INLINE_TABLE_ACCESSOR(generic_signature_index ) INLINE_TABLE_ACCESSOR(method_annotations_length) INLINE_TABLE_ACCESSOR (parameter_annotations_length) INLINE_TABLE_ACCESSOR(type_annotations_length ) INLINE_TABLE_ACCESSOR(default_annotations_length) | |||
161 | }; | |||
162 | #undef INLINE_TABLE_ACCESSOR | |||
163 | #undef INLINE_TABLE_NULL | |||
164 | #undef INLINE_TABLE_INIT | |||
165 | #undef INLINE_TABLE_PARAM | |||
166 | #undef INLINE_TABLE_DECLARE | |||
167 | ||||
168 | class ConstMethod : public MetaspaceObj { | |||
169 | friend class VMStructs; | |||
170 | friend class JVMCIVMStructs; | |||
171 | ||||
172 | public: | |||
173 | typedef enum { NORMAL, OVERPASS } MethodType; | |||
174 | ||||
175 | private: | |||
176 | enum { | |||
177 | _has_linenumber_table = 0x0001, | |||
178 | _has_checked_exceptions = 0x0002, | |||
179 | _has_localvariable_table = 0x0004, | |||
180 | _has_exception_table = 0x0008, | |||
181 | _has_generic_signature = 0x0010, | |||
182 | _has_method_parameters = 0x0020, | |||
183 | _is_overpass = 0x0040, | |||
184 | _has_method_annotations = 0x0080, | |||
185 | _has_parameter_annotations = 0x0100, | |||
186 | _has_type_annotations = 0x0200, | |||
187 | _has_default_annotations = 0x0400 | |||
188 | }; | |||
189 | ||||
190 | // Bit vector of signature | |||
191 | // Callers interpret 0=not initialized yet and | |||
192 | // -1=too many args to fix, must parse the slow way. | |||
193 | // The real initial value is special to account for nonatomicity of 64 bit | |||
194 | // loads and stores. This value may updated and read without a lock by | |||
195 | // multiple threads, so is volatile. | |||
196 | volatile uint64_t _fingerprint; | |||
197 | ||||
198 | // If you add a new field that points to any metaspace object, you | |||
199 | // must add this field to ConstMethod::metaspace_pointers_do(). | |||
200 | ||||
201 | ConstantPool* _constants; // Constant pool | |||
202 | ||||
203 | // Raw stackmap data for the method | |||
204 | Array<u1>* _stackmap_data; | |||
205 | ||||
206 | int _constMethod_size; | |||
207 | u2 _flags; | |||
208 | u1 _result_type; // BasicType of result | |||
209 | ||||
210 | // Size of Java bytecodes allocated immediately after Method*. | |||
211 | u2 _code_size; | |||
212 | u2 _name_index; // Method name (index in constant pool) | |||
213 | u2 _signature_index; // Method signature (index in constant pool) | |||
214 | u2 _method_idnum; // unique identification number for the method within the class | |||
215 | // initially corresponds to the index into the methods array. | |||
216 | // but this may change with redefinition | |||
217 | u2 _max_stack; // Maximum number of entries on the expression stack | |||
218 | u2 _max_locals; // Number of local variables used by this method | |||
219 | u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words | |||
220 | u2 _orig_method_idnum; // Original unique identification number for the method | |||
221 | ||||
222 | // Constructor | |||
223 | ConstMethod(int byte_code_size, | |||
224 | InlineTableSizes* sizes, | |||
225 | MethodType is_overpass, | |||
226 | int size); | |||
227 | public: | |||
228 | ||||
229 | static ConstMethod* allocate(ClassLoaderData* loader_data, | |||
230 | int byte_code_size, | |||
231 | InlineTableSizes* sizes, | |||
232 | MethodType mt, | |||
233 | TRAPSJavaThread* __the_thread__); | |||
234 | ||||
235 | // Inlined tables | |||
236 | void set_inlined_tables_length(InlineTableSizes* sizes); | |||
237 | ||||
238 | bool has_generic_signature() const | |||
239 | { return (_flags & _has_generic_signature) != 0; } | |||
240 | ||||
241 | bool has_linenumber_table() const | |||
242 | { return (_flags & _has_linenumber_table) != 0; } | |||
243 | ||||
244 | bool has_checked_exceptions() const | |||
245 | { return (_flags & _has_checked_exceptions) != 0; } | |||
246 | ||||
247 | bool has_localvariable_table() const | |||
248 | { return (_flags & _has_localvariable_table) != 0; } | |||
249 | ||||
250 | bool has_exception_handler() const | |||
251 | { return (_flags & _has_exception_table) != 0; } | |||
252 | ||||
253 | bool has_method_parameters() const | |||
254 | { return (_flags & _has_method_parameters) != 0; } | |||
255 | ||||
256 | MethodType method_type() const { | |||
257 | return ((_flags & _is_overpass) == 0) ? NORMAL : OVERPASS; | |||
258 | } | |||
259 | ||||
260 | void set_method_type(MethodType mt) { | |||
261 | if (mt == NORMAL) { | |||
262 | _flags &= ~(_is_overpass); | |||
263 | } else { | |||
264 | _flags |= _is_overpass; | |||
265 | } | |||
266 | } | |||
267 | ||||
268 | // constant pool | |||
269 | ConstantPool* constants() const { return _constants; } | |||
270 | void set_constants(ConstantPool* c) { _constants = c; } | |||
271 | ||||
272 | Method* method() const; | |||
273 | ||||
274 | // stackmap table data | |||
275 | Array<u1>* stackmap_data() const { return _stackmap_data; } | |||
276 | void set_stackmap_data(Array<u1>* sd) { _stackmap_data = sd; } | |||
277 | void copy_stackmap_data(ClassLoaderData* loader_data, u1* sd, int length, TRAPSJavaThread* __the_thread__); | |||
278 | bool has_stackmap_table() const { return _stackmap_data != NULL__null; } | |||
279 | ||||
280 | void init_fingerprint() { | |||
281 | const uint64_t initval = UCONST64(0x8000000000000000)(0x8000000000000000ULL); | |||
282 | _fingerprint = initval; | |||
283 | } | |||
284 | ||||
285 | uint64_t fingerprint() const { | |||
286 | // Since reads aren't atomic for 64 bits, if any of the high or low order | |||
287 | // word is the initial value, return 0. See init_fingerprint for initval. | |||
288 | uint high_fp = (uint)(_fingerprint >> 32); | |||
289 | if ((int) _fingerprint == 0 || high_fp == 0x80000000) { | |||
290 | return 0L; | |||
291 | } else { | |||
292 | return _fingerprint; | |||
293 | } | |||
294 | } | |||
295 | ||||
296 | uint64_t set_fingerprint(uint64_t new_fingerprint) { | |||
297 | #ifdef ASSERT1 | |||
298 | // Assert only valid if complete/valid 64 bit _fingerprint value is read. | |||
299 | uint64_t oldfp = fingerprint(); | |||
300 | #endif // ASSERT | |||
301 | _fingerprint = new_fingerprint; | |||
302 | assert(oldfp == 0L || new_fingerprint == oldfp,do { if (!(oldfp == 0L || new_fingerprint == oldfp)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/constMethod.hpp" , 303, "assert(" "oldfp == 0L || new_fingerprint == oldfp" ") failed" , "fingerprint cannot change"); ::breakpoint(); } } while (0) | |||
303 | "fingerprint cannot change")do { if (!(oldfp == 0L || new_fingerprint == oldfp)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/constMethod.hpp" , 303, "assert(" "oldfp == 0L || new_fingerprint == oldfp" ") failed" , "fingerprint cannot change"); ::breakpoint(); } } while (0); | |||
304 | assert(((new_fingerprint >> 32) != 0x80000000) && (int)new_fingerprint !=0,do { if (!(((new_fingerprint >> 32) != 0x80000000) && (int)new_fingerprint !=0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/constMethod.hpp" , 305, "assert(" "((new_fingerprint >> 32) != 0x80000000) && (int)new_fingerprint !=0" ") failed", "fingerprint should call init to set initial value" ); ::breakpoint(); } } while (0) | |||
305 | "fingerprint should call init to set initial value")do { if (!(((new_fingerprint >> 32) != 0x80000000) && (int)new_fingerprint !=0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/constMethod.hpp" , 305, "assert(" "((new_fingerprint >> 32) != 0x80000000) && (int)new_fingerprint !=0" ") failed", "fingerprint should call init to set initial value" ); ::breakpoint(); } } while (0); | |||
306 | return new_fingerprint; | |||
307 | } | |||
308 | ||||
309 | // name | |||
310 | int name_index() const { return _name_index; } | |||
311 | void set_name_index(int index) { _name_index = index; } | |||
312 | ||||
313 | // signature | |||
314 | int signature_index() const { return _signature_index; } | |||
315 | void set_signature_index(int index) { _signature_index = index; } | |||
316 | ||||
317 | // generics support | |||
318 | int generic_signature_index() const { | |||
319 | if (has_generic_signature()) { | |||
320 | return *generic_signature_index_addr(); | |||
321 | } else { | |||
322 | return 0; | |||
323 | } | |||
324 | } | |||
325 | void set_generic_signature_index(u2 index) { | |||
326 | assert(has_generic_signature(), "")do { if (!(has_generic_signature())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/constMethod.hpp" , 326, "assert(" "has_generic_signature()" ") failed", ""); :: breakpoint(); } } while (0); | |||
327 | u2* addr = generic_signature_index_addr(); | |||
328 | *addr = index; | |||
329 | } | |||
330 | ||||
331 | // Sizing | |||
332 | static int header_size() { | |||
333 | return align_up((int)sizeof(ConstMethod), wordSize) / wordSize; | |||
334 | } | |||
335 | ||||
336 | // Size needed | |||
337 | static int size(int code_size, InlineTableSizes* sizes); | |||
338 | ||||
339 | int size() const { return _constMethod_size;} | |||
340 | void set_constMethod_size(int size) { _constMethod_size = size; } | |||
341 | ||||
342 | // ConstMethods should be stored in the read-only region of CDS archive. | |||
343 | static bool is_read_only_by_default() { return true; } | |||
344 | ||||
345 | // code size | |||
346 | int code_size() const { return _code_size; } | |||
347 | void set_code_size(int size) { | |||
348 | assert(max_method_code_size < (1 << 16),do { if (!(max_method_code_size < (1 << 16))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/constMethod.hpp" , 349, "assert(" "max_method_code_size < (1 << 16)" ") failed" , "u2 is too small to hold method code size in general"); ::breakpoint (); } } while (0) | |||
349 | "u2 is too small to hold method code size in general")do { if (!(max_method_code_size < (1 << 16))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/constMethod.hpp" , 349, "assert(" "max_method_code_size < (1 << 16)" ") failed" , "u2 is too small to hold method code size in general"); ::breakpoint (); } } while (0); | |||
350 | assert(0 <= size && size <= max_method_code_size, "invalid code size")do { if (!(0 <= size && size <= max_method_code_size )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/constMethod.hpp" , 350, "assert(" "0 <= size && size <= max_method_code_size" ") failed", "invalid code size"); ::breakpoint(); } } while ( 0); | |||
351 | _code_size = size; | |||
352 | } | |||
353 | ||||
354 | // linenumber table - note that length is unknown until decompression, | |||
355 | // see class CompressedLineNumberReadStream. | |||
356 | u_char* compressed_linenumber_table() const; // not preserved by gc | |||
357 | u2* generic_signature_index_addr() const; | |||
358 | u2* checked_exceptions_length_addr() const; | |||
359 | u2* localvariable_table_length_addr() const; | |||
360 | u2* exception_table_length_addr() const; | |||
361 | u2* method_parameters_length_addr() const; | |||
362 | ||||
363 | // checked exceptions | |||
364 | int checked_exceptions_length() const; | |||
365 | CheckedExceptionElement* checked_exceptions_start() const; | |||
366 | ||||
367 | // localvariable table | |||
368 | int localvariable_table_length() const; | |||
369 | LocalVariableTableElement* localvariable_table_start() const; | |||
370 | ||||
371 | // exception table | |||
372 | int exception_table_length() const; | |||
373 | ExceptionTableElement* exception_table_start() const; | |||
374 | ||||
375 | // method parameters table | |||
376 | ||||
377 | // This returns -1 if no parameters are present, a non-negative | |||
378 | // value otherwise. Note: sometimes, there are 0-length parameters | |||
379 | // attributes that must be reported up to the reflection API all the | |||
380 | // same. | |||
381 | int method_parameters_length() const; | |||
382 | MethodParametersElement* method_parameters_start() const; | |||
383 | ||||
384 | // method annotations | |||
385 | bool has_method_annotations() const | |||
386 | { return (_flags & _has_method_annotations) != 0; } | |||
387 | ||||
388 | bool has_parameter_annotations() const | |||
389 | { return (_flags & _has_parameter_annotations) != 0; } | |||
390 | ||||
391 | bool has_type_annotations() const | |||
392 | { return (_flags & _has_type_annotations) != 0; } | |||
393 | ||||
394 | bool has_default_annotations() const | |||
395 | { return (_flags & _has_default_annotations) != 0; } | |||
396 | ||||
397 | ||||
398 | AnnotationArray** method_annotations_addr() const; | |||
399 | AnnotationArray* method_annotations() const { | |||
400 | return has_method_annotations() ? *(method_annotations_addr()) : NULL__null; | |||
401 | } | |||
402 | void set_method_annotations(AnnotationArray* anno) { | |||
403 | *(method_annotations_addr()) = anno; | |||
404 | } | |||
405 | ||||
406 | AnnotationArray** parameter_annotations_addr() const; | |||
407 | AnnotationArray* parameter_annotations() const { | |||
408 | return has_parameter_annotations() ? *(parameter_annotations_addr()) : NULL__null; | |||
409 | } | |||
410 | void set_parameter_annotations(AnnotationArray* anno) { | |||
411 | *(parameter_annotations_addr()) = anno; | |||
412 | } | |||
413 | ||||
414 | AnnotationArray** type_annotations_addr() const; | |||
415 | AnnotationArray* type_annotations() const { | |||
416 | return has_type_annotations() ? *(type_annotations_addr()) : NULL__null; | |||
417 | } | |||
418 | void set_type_annotations(AnnotationArray* anno) { | |||
419 | *(type_annotations_addr()) = anno; | |||
420 | } | |||
421 | ||||
422 | AnnotationArray** default_annotations_addr() const; | |||
423 | AnnotationArray* default_annotations() const { | |||
424 | return has_default_annotations() ? *(default_annotations_addr()) : NULL__null; | |||
425 | } | |||
426 | void set_default_annotations(AnnotationArray* anno) { | |||
427 | *(default_annotations_addr()) = anno; | |||
428 | } | |||
429 | ||||
430 | int method_annotations_length() const { | |||
431 | return has_method_annotations() ? method_annotations()->length() : 0; | |||
432 | } | |||
433 | int parameter_annotations_length() const { | |||
434 | return has_parameter_annotations() ? parameter_annotations()->length() : 0; | |||
435 | } | |||
436 | int type_annotations_length() const { | |||
437 | return has_type_annotations() ? type_annotations()->length() : 0; | |||
438 | } | |||
439 | int default_annotations_length() const { | |||
440 | return has_default_annotations() ? default_annotations()->length() : 0; | |||
441 | } | |||
442 | ||||
443 | // Copy annotations from other ConstMethod | |||
444 | void copy_annotations_from(ClassLoaderData* loader_data, ConstMethod* cm, TRAPSJavaThread* __the_thread__); | |||
445 | ||||
446 | // byte codes | |||
447 | void set_code(address code) { | |||
448 | if (code_size() > 0) { | |||
449 | memcpy(code_base(), code, code_size()); | |||
| ||||
450 | } | |||
451 | } | |||
452 | address code_base() const { return (address) (this+1); } | |||
453 | address code_end() const { return code_base() + code_size(); } | |||
454 | bool contains(address bcp) const { return code_base() <= bcp | |||
455 | && bcp < code_end(); } | |||
456 | // Offset to bytecodes | |||
457 | static ByteSize codes_offset() | |||
458 | { return in_ByteSize(sizeof(ConstMethod)); } | |||
459 | ||||
460 | static ByteSize constants_offset() | |||
461 | { return byte_offset_of(ConstMethod, _constants)in_ByteSize((int)(size_t)((intx)&(((ConstMethod*)16)-> _constants) - 16)); } | |||
462 | ||||
463 | static ByteSize max_stack_offset() | |||
464 | { return byte_offset_of(ConstMethod, _max_stack)in_ByteSize((int)(size_t)((intx)&(((ConstMethod*)16)-> _max_stack) - 16)); } | |||
465 | static ByteSize size_of_locals_offset() | |||
466 | { return byte_offset_of(ConstMethod, _max_locals)in_ByteSize((int)(size_t)((intx)&(((ConstMethod*)16)-> _max_locals) - 16)); } | |||
467 | static ByteSize size_of_parameters_offset() | |||
468 | { return byte_offset_of(ConstMethod, _size_of_parameters)in_ByteSize((int)(size_t)((intx)&(((ConstMethod*)16)-> _size_of_parameters) - 16)); } | |||
469 | ||||
470 | static ByteSize result_type_offset() | |||
471 | { return byte_offset_of(ConstMethod, _result_type)in_ByteSize((int)(size_t)((intx)&(((ConstMethod*)16)-> _result_type) - 16)); } | |||
472 | ||||
473 | // Unique id for the method | |||
474 | static const u2 MAX_IDNUM; | |||
475 | static const u2 UNSET_IDNUM; | |||
476 | u2 method_idnum() const { return _method_idnum; } | |||
477 | void set_method_idnum(u2 idnum) { _method_idnum = idnum; } | |||
478 | ||||
479 | u2 orig_method_idnum() const { return _orig_method_idnum; } | |||
480 | void set_orig_method_idnum(u2 idnum) { _orig_method_idnum = idnum; } | |||
481 | ||||
482 | // max stack | |||
483 | int max_stack() const { return _max_stack; } | |||
484 | void set_max_stack(int size) { _max_stack = size; } | |||
485 | ||||
486 | // max locals | |||
487 | int max_locals() const { return _max_locals; } | |||
488 | void set_max_locals(int size) { _max_locals = size; } | |||
489 | ||||
490 | // size of parameters | |||
491 | int size_of_parameters() const { return _size_of_parameters; } | |||
492 | void set_size_of_parameters(int size) { _size_of_parameters = size; } | |||
493 | ||||
494 | // result type (basic type of return value) | |||
495 | BasicType result_type() const { assert(_result_type >= T_BOOLEAN, "Must be set")do { if (!(_result_type >= T_BOOLEAN)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/constMethod.hpp" , 495, "assert(" "_result_type >= T_BOOLEAN" ") failed", "Must be set" ); ::breakpoint(); } } while (0); | |||
496 | return (BasicType)_result_type; } | |||
497 | ||||
498 | void set_result_type(BasicType rt) { assert(rt < 16, "result type too large")do { if (!(rt < 16)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/oops/constMethod.hpp" , 498, "assert(" "rt < 16" ") failed", "result type too large" ); ::breakpoint(); } } while (0); | |||
499 | _result_type = (u1)rt; } | |||
500 | // Deallocation for RedefineClasses | |||
501 | void deallocate_contents(ClassLoaderData* loader_data); | |||
502 | bool is_klass() const { return false; } | |||
503 | DEBUG_ONLY(bool on_stack() { return false; })bool on_stack() { return false; } | |||
504 | ||||
505 | void metaspace_pointers_do(MetaspaceClosure* it); | |||
506 | MetaspaceObj::Type type() const { return ConstMethodType; } | |||
507 | private: | |||
508 | // Since the size of the compressed line number table is unknown, the | |||
509 | // offsets of the other variable sized sections are computed backwards | |||
510 | // from the end of the ConstMethod*. | |||
511 | ||||
512 | // First byte after ConstMethod* | |||
513 | address constMethod_end() const | |||
514 | { return (address)((intptr_t*)this + _constMethod_size); } | |||
515 | ||||
516 | // Last short in ConstMethod* | |||
517 | u2* last_u2_element() const; | |||
518 | ||||
519 | public: | |||
520 | // Printing | |||
521 | void print_on (outputStream* st) const; | |||
522 | void print_value_on(outputStream* st) const; | |||
523 | ||||
524 | const char* internal_name() const { return "{constMethod}"; } | |||
525 | ||||
526 | // Verify | |||
527 | void verify_on(outputStream* st); | |||
528 | }; | |||
529 | ||||
530 | #endif // SHARE_OOPS_CONSTMETHOD_HPP |