File: | jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp |
Warning: | line 1471, column 21 Value stored to 'klass_name' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #include "precompiled.hpp" |
26 | #include "jvm.h" |
27 | #include "classfile/classFileParser.hpp" |
28 | #include "classfile/classFileStream.hpp" |
29 | #include "classfile/classLoadInfo.hpp" |
30 | #include "classfile/javaClasses.inline.hpp" |
31 | #include "classfile/moduleEntry.hpp" |
32 | #include "classfile/modules.hpp" |
33 | #include "classfile/stackMapTable.hpp" |
34 | #include "classfile/symbolTable.hpp" |
35 | #include "classfile/systemDictionary.hpp" |
36 | #include "classfile/verificationType.hpp" |
37 | #include "interpreter/bytecodes.hpp" |
38 | #include "jfr/instrumentation/jfrEventClassTransformer.hpp" |
39 | #include "jfr/jfr.hpp" |
40 | #include "jfr/jni/jfrJavaSupport.hpp" |
41 | #include "jfr/jni/jfrUpcalls.hpp" |
42 | #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp" |
43 | #include "jfr/support/jfrJdkJfrEvent.hpp" |
44 | #include "jfr/utilities/jfrBigEndian.hpp" |
45 | #include "jfr/writers/jfrBigEndianWriter.hpp" |
46 | #include "logging/log.hpp" |
47 | #include "memory/allocation.inline.hpp" |
48 | #include "memory/resourceArea.hpp" |
49 | #include "oops/array.hpp" |
50 | #include "oops/instanceKlass.hpp" |
51 | #include "oops/klass.inline.hpp" |
52 | #include "oops/method.hpp" |
53 | #include "prims/jvmtiRedefineClasses.hpp" |
54 | #include "runtime/handles.inline.hpp" |
55 | #include "runtime/jniHandles.hpp" |
56 | #include "runtime/os.hpp" |
57 | #include "runtime/thread.inline.hpp" |
58 | #include "utilities/exceptions.hpp" |
59 | #include "utilities/globalDefinitions.hpp" |
60 | #include "utilities/macros.hpp" |
61 | |
62 | static const u2 number_of_new_methods = 5; |
63 | static const u2 number_of_new_fields = 3; |
64 | static const int extra_stream_bytes = 0x280; |
65 | static const u2 invalid_cp_index = 0; |
66 | |
67 | static const char* utf8_constants[] = { |
68 | "Code", // 0 |
69 | "J", // 1 |
70 | "commit", // 2 |
71 | "eventHandler", // 3 |
72 | "duration", // 4 |
73 | "begin", // 5 |
74 | "()V", // 6 |
75 | "isEnabled", // 7 |
76 | "()Z", // 8 |
77 | "end", // 9 |
78 | "shouldCommit", // 10 |
79 | "startTime", // 11 // LAST_REQUIRED_UTF8 |
80 | "Ljdk/jfr/internal/handlers/EventHandler;", // 12 |
81 | "Ljava/lang/Object;", // 13 |
82 | "<clinit>", // 14 |
83 | "jdk/jfr/FlightRecorder", // 15 |
84 | "register", // 16 |
85 | "(Ljava/lang/Class;)V", // 17 |
86 | "StackMapTable", // 18 |
87 | "Exceptions", // 19 |
88 | "LineNumberTable", // 20 |
89 | "LocalVariableTable", // 21 |
90 | "LocalVariableTypeTable", // 22 |
91 | "RuntimeVisibleAnnotation", // 23 |
92 | }; |
93 | |
94 | enum utf8_req_symbols { |
95 | UTF8_REQ_Code, |
96 | UTF8_REQ_J_FIELD_DESC, |
97 | UTF8_REQ_commit, |
98 | UTF8_REQ_eventHandler, |
99 | UTF8_REQ_duration, |
100 | UTF8_REQ_begin, |
101 | UTF8_REQ_EMPTY_VOID_METHOD_DESC, |
102 | UTF8_REQ_isEnabled, |
103 | UTF8_REQ_EMPTY_BOOLEAN_METHOD_DESC, |
104 | UTF8_REQ_end, |
105 | UTF8_REQ_shouldCommit, |
106 | UTF8_REQ_startTime, |
107 | NOF_UTF8_REQ_SYMBOLS |
108 | }; |
109 | |
110 | enum utf8_opt_symbols { |
111 | UTF8_OPT_eventHandler_FIELD_DESC = NOF_UTF8_REQ_SYMBOLS, |
112 | UTF8_OPT_LjavaLangObject, |
113 | UTF8_OPT_clinit, |
114 | UTF8_OPT_FlightRecorder, |
115 | UTF8_OPT_register, |
116 | UTF8_OPT_CLASS_VOID_METHOD_DESC, |
117 | UTF8_OPT_StackMapTable, |
118 | UTF8_OPT_Exceptions, |
119 | UTF8_OPT_LineNumberTable, |
120 | UTF8_OPT_LocalVariableTable, |
121 | UTF8_OPT_LocalVariableTypeTable, |
122 | UTF8_OPT_RuntimeVisibleAnnotation, |
123 | NOF_UTF8_SYMBOLS |
124 | }; |
125 | |
126 | static u1 empty_void_method_code_attribute[] = { |
127 | 0x0, |
128 | 0x0, |
129 | 0x0, |
130 | 0xd, // attribute len |
131 | 0x0, |
132 | 0x0, // max stack |
133 | 0x0, |
134 | 0x1, // max locals |
135 | 0x0, |
136 | 0x0, |
137 | 0x0, |
138 | 0x1, // code length |
139 | Bytecodes::_return, |
140 | 0x0, |
141 | 0x0, // ex table len |
142 | 0x0, |
143 | 0x0 // attributes_count |
144 | }; |
145 | |
146 | static u1 boolean_method_code_attribute[] = { |
147 | 0x0, |
148 | 0x0, |
149 | 0x0, |
150 | 0xe, |
151 | 0x0, |
152 | 0x1, // max stack |
153 | 0x0, |
154 | 0x1, // max locals |
155 | 0x0, |
156 | 0x0, |
157 | 0x0, |
158 | 0x2, |
159 | Bytecodes::_iconst_0, |
160 | Bytecodes::_ireturn, |
161 | 0x0, |
162 | 0x0, // ex table len |
163 | 0x0, |
164 | 0x0, // attributes_count |
165 | }; |
166 | |
167 | // annotation processing support |
168 | |
169 | enum { // initial annotation layout |
170 | atype_off = 0, // utf8 such as 'Ljava/lang/annotation/Retention;' |
171 | count_off = 2, // u2 such as 1 (one value) |
172 | member_off = 4, // utf8 such as 'value' |
173 | tag_off = 6, // u1 such as 'c' (type) or 'e' (enum) |
174 | e_tag_val = 'e', |
175 | e_type_off = 7, // utf8 such as 'Ljava/lang/annotation/RetentionPolicy;' |
176 | e_con_off = 9, // utf8 payload, such as 'SOURCE', 'CLASS', 'RUNTIME' |
177 | e_size = 11, // end of 'e' annotation |
178 | c_tag_val = 'c', // payload is type |
179 | c_con_off = 7, // utf8 payload, such as 'I' |
180 | c_size = 9, // end of 'c' annotation |
181 | s_tag_val = 's', // payload is String |
182 | s_con_off = 7, // utf8 payload, such as 'Ljava/lang/String;' |
183 | s_size = 9, |
184 | min_size = 6 // smallest possible size (zero members) |
185 | }; |
186 | |
187 | static int skip_annotation_value(const address, int, int); // fwd decl |
188 | |
189 | // Skip an annotation. Return >=limit if there is any problem. |
190 | static int next_annotation_index(const address buffer, int limit, int index) { |
191 | assert(buffer != NULL, "invariant")do { if (!(buffer != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 191, "assert(" "buffer != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); |
192 | index += 2; // skip atype |
193 | if ((index += 2) >= limit) { |
194 | return limit; |
195 | } |
196 | int nof_members = JfrBigEndian::read<u2>(buffer + index - 2); |
197 | while (--nof_members >= 0 && index < limit) { |
198 | index += 2; // skip member |
199 | index = skip_annotation_value(buffer, limit, index); |
200 | } |
201 | return index; |
202 | } |
203 | |
204 | // Skip an annotation value. Return >=limit if there is any problem. |
205 | static int skip_annotation_value(const address buffer, int limit, int index) { |
206 | assert(buffer != NULL, "invariant")do { if (!(buffer != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 206, "assert(" "buffer != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); |
207 | // value := switch (tag:u1) { |
208 | // case B, C, I, S, Z, D, F, J, c: con:u2; |
209 | // case e: e_class:u2 e_name:u2; |
210 | // case s: s_con:u2; |
211 | // case [: do(nval:u2) {value}; |
212 | // case @: annotation; |
213 | // case s: s_con:u2; |
214 | // } |
215 | if ((index += 1) >= limit) { |
216 | return limit; |
217 | } |
218 | const u1 tag = buffer[index - 1]; |
219 | switch (tag) { |
220 | case 'B': |
221 | case 'C': |
222 | case 'I': |
223 | case 'S': |
224 | case 'Z': |
225 | case 'D': |
226 | case 'F': |
227 | case 'J': |
228 | case 'c': |
229 | case 's': |
230 | index += 2; // skip con or s_con |
231 | break; |
232 | case 'e': |
233 | index += 4; // skip e_class, e_name |
234 | break; |
235 | case '[': |
236 | { |
237 | if ((index += 2) >= limit) { |
238 | return limit; |
239 | } |
240 | int nof_values = JfrBigEndian::read<u2>(buffer + index - 2); |
241 | while (--nof_values >= 0 && index < limit) { |
242 | index = skip_annotation_value(buffer, limit, index); |
243 | } |
244 | } |
245 | break; |
246 | case '@': |
247 | index = next_annotation_index(buffer, limit, index); |
248 | break; |
249 | default: |
250 | return limit; // bad tag byte |
251 | } |
252 | return index; |
253 | } |
254 | |
255 | static const u2 number_of_elements_offset = (u2)2; |
256 | static const u2 element_name_offset = (u2)(number_of_elements_offset + 2); |
257 | static const u2 element_name_size = (u2)2; |
258 | static const u2 value_type_relative_offset = (u2)2; |
259 | static const u2 value_relative_offset = (u2)(value_type_relative_offset + 1); |
260 | |
261 | // see JVMS - 4.7.16. The RuntimeVisibleAnnotations Attribute |
262 | |
263 | class AnnotationElementIterator : public StackObj { |
264 | private: |
265 | const InstanceKlass* _ik; |
266 | const address _buffer; |
267 | const u2 _limit; // length of annotation |
268 | mutable u2 _current; // element |
269 | mutable u2 _next; // element |
270 | u2 value_index() const { |
271 | return JfrBigEndian::read<u2>(_buffer + _current + value_relative_offset); |
272 | } |
273 | |
274 | public: |
275 | AnnotationElementIterator(const InstanceKlass* ik, address buffer, u2 limit) : _ik(ik), |
276 | _buffer(buffer), |
277 | _limit(limit), |
278 | _current(element_name_offset), |
279 | _next(element_name_offset) { |
280 | assert(_buffer != NULL, "invariant")do { if (!(_buffer != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 280, "assert(" "_buffer != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
281 | assert(_next == element_name_offset, "invariant")do { if (!(_next == element_name_offset)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 281, "assert(" "_next == element_name_offset" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
282 | assert(_current == element_name_offset, "invariant")do { if (!(_current == element_name_offset)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 282, "assert(" "_current == element_name_offset" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
283 | } |
284 | |
285 | bool has_next() const { |
286 | return _next < _limit; |
287 | } |
288 | |
289 | void move_to_next() const { |
290 | assert(has_next(), "invariant")do { if (!(has_next())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 290, "assert(" "has_next()" ") failed", "invariant"); ::breakpoint (); } } while (0); |
291 | _current = _next; |
292 | if (_next < _limit) { |
293 | _next = skip_annotation_value(_buffer, _limit, _next + element_name_size); |
294 | } |
295 | assert(_next <= _limit, "invariant")do { if (!(_next <= _limit)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 295, "assert(" "_next <= _limit" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
296 | assert(_current <= _limit, "invariant")do { if (!(_current <= _limit)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 296, "assert(" "_current <= _limit" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
297 | } |
298 | |
299 | u2 number_of_elements() const { |
300 | return JfrBigEndian::read<u2>(_buffer + number_of_elements_offset); |
301 | } |
302 | |
303 | const Symbol* name() const { |
304 | assert(_current < _next, "invariant")do { if (!(_current < _next)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 304, "assert(" "_current < _next" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
305 | return _ik->constants()->symbol_at(JfrBigEndian::read<u2>(_buffer + _current)); |
306 | } |
307 | |
308 | char value_type() const { |
309 | return JfrBigEndian::read<u1>(_buffer + _current + value_type_relative_offset); |
310 | } |
311 | |
312 | jint read_int() const { |
313 | return _ik->constants()->int_at(value_index()); |
314 | } |
315 | |
316 | bool read_bool() const { |
317 | return read_int() != 0; |
318 | } |
319 | }; |
320 | |
321 | class AnnotationIterator : public StackObj { |
322 | private: |
323 | const InstanceKlass* _ik; |
324 | // ensure _limit field is declared before _buffer |
325 | u2 _limit; // length of annotations array |
326 | const address _buffer; |
327 | mutable u2 _current; // annotation |
328 | mutable u2 _next; // annotation |
329 | |
330 | public: |
331 | AnnotationIterator(const InstanceKlass* ik, AnnotationArray* ar) : _ik(ik), |
332 | _limit(ar != NULL__null ? ar->length() : 0), |
333 | _buffer(_limit > 2 ? ar->adr_at(2) : NULL__null), |
334 | _current(0), |
335 | _next(0) { |
336 | if (_buffer != NULL__null) { |
337 | _limit -= 2; // subtract sizeof(u2) number of annotations field |
338 | } |
339 | } |
340 | bool has_next() const { |
341 | return _next < _limit; |
342 | } |
343 | |
344 | void move_to_next() const { |
345 | assert(has_next(), "invariant")do { if (!(has_next())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 345, "assert(" "has_next()" ") failed", "invariant"); ::breakpoint (); } } while (0); |
346 | _current = _next; |
347 | if (_next < _limit) { |
348 | _next = next_annotation_index(_buffer, _limit, _next); |
349 | } |
350 | assert(_next <= _limit, "invariant")do { if (!(_next <= _limit)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 350, "assert(" "_next <= _limit" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
351 | assert(_current <= _limit, "invariant")do { if (!(_current <= _limit)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 351, "assert(" "_current <= _limit" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
352 | } |
353 | const AnnotationElementIterator elements() const { |
354 | assert(_current < _next, "invariant")do { if (!(_current < _next)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 354, "assert(" "_current < _next" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
355 | return AnnotationElementIterator(_ik, _buffer + _current, _next - _current); |
356 | } |
357 | const Symbol* type() const { |
358 | assert(_buffer != NULL, "invariant")do { if (!(_buffer != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 358, "assert(" "_buffer != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
359 | assert(_current < _limit, "invariant")do { if (!(_current < _limit)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 359, "assert(" "_current < _limit" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
360 | return _ik->constants()->symbol_at(JfrBigEndian::read<u2>(_buffer + _current)); |
361 | } |
362 | }; |
363 | |
364 | static const char value_name[] = "value"; |
365 | static bool has_annotation(const InstanceKlass* ik, const Symbol* annotation_type, bool& value) { |
366 | assert(annotation_type != NULL, "invariant")do { if (!(annotation_type != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 366, "assert(" "annotation_type != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
367 | AnnotationArray* class_annotations = ik->class_annotations(); |
368 | if (class_annotations == NULL__null) { |
369 | return false; |
370 | } |
371 | |
372 | const AnnotationIterator annotation_iterator(ik, class_annotations); |
373 | while (annotation_iterator.has_next()) { |
374 | annotation_iterator.move_to_next(); |
375 | if (annotation_iterator.type() == annotation_type) { |
376 | // target annotation found |
377 | static const Symbol* value_symbol = |
378 | SymbolTable::probe(value_name, sizeof value_name - 1); |
379 | assert(value_symbol != NULL, "invariant")do { if (!(value_symbol != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 379, "assert(" "value_symbol != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
380 | const AnnotationElementIterator element_iterator = annotation_iterator.elements(); |
381 | while (element_iterator.has_next()) { |
382 | element_iterator.move_to_next(); |
383 | if (value_symbol == element_iterator.name()) { |
384 | // "value" element |
385 | assert('Z' == element_iterator.value_type(), "invariant")do { if (!('Z' == element_iterator.value_type())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 385, "assert(" "'Z' == element_iterator.value_type()" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
386 | value = element_iterator.read_bool(); |
387 | return true; |
388 | } |
389 | } |
390 | } |
391 | } |
392 | return false; |
393 | } |
394 | |
395 | // Evaluate to the value of the first found Symbol* annotation type. |
396 | // Searching moves upwards in the klass hierarchy in order to support |
397 | // inherited annotations in addition to the ability to override. |
398 | static bool annotation_value(const InstanceKlass* ik, const Symbol* annotation_type, bool& value) { |
399 | assert(ik != NULL, "invariant")do { if (!(ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 399, "assert(" "ik != __null" ") failed", "invariant"); ::breakpoint (); } } while (0); |
400 | assert(annotation_type != NULL, "invariant")do { if (!(annotation_type != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 400, "assert(" "annotation_type != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
401 | assert(JdkJfrEvent::is_a(ik), "invariant")do { if (!(JdkJfrEvent::is_a(ik))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 401, "assert(" "JdkJfrEvent::is_a(ik)" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
402 | if (has_annotation(ik, annotation_type, value)) { |
403 | return true; |
404 | } |
405 | InstanceKlass* const super = InstanceKlass::cast(ik->super()); |
406 | return super != NULL__null && JdkJfrEvent::is_a(super) ? annotation_value(super, annotation_type, value) : false; |
407 | } |
408 | |
409 | static const char jdk_jfr_module_name[] = "jdk.jfr"; |
410 | |
411 | static bool java_base_can_read_jdk_jfr() { |
412 | static bool can_read = false; |
413 | if (can_read) { |
414 | return true; |
415 | } |
416 | static Symbol* jdk_jfr_module_symbol = NULL__null; |
417 | if (jdk_jfr_module_symbol == NULL__null) { |
418 | jdk_jfr_module_symbol = SymbolTable::probe(jdk_jfr_module_name, sizeof jdk_jfr_module_name - 1); |
419 | if (jdk_jfr_module_symbol == NULL__null) { |
420 | return false; |
421 | } |
422 | } |
423 | assert(jdk_jfr_module_symbol != NULL, "invariant")do { if (!(jdk_jfr_module_symbol != __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 423, "assert(" "jdk_jfr_module_symbol != __null" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
424 | ModuleEntryTable* const table = Modules::get_module_entry_table(Handle()); |
425 | assert(table != NULL, "invariant")do { if (!(table != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 425, "assert(" "table != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
426 | const ModuleEntry* const java_base_module = table->javabase_moduleEntry(); |
427 | if (java_base_module == NULL__null) { |
428 | return false; |
429 | } |
430 | assert(java_base_module != NULL, "invariant")do { if (!(java_base_module != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 430, "assert(" "java_base_module != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
431 | ModuleEntry* const jdk_jfr_module = table->lookup_only(jdk_jfr_module_symbol); |
432 | if (jdk_jfr_module == NULL__null) { |
433 | return false; |
434 | } |
435 | assert(jdk_jfr_module != NULL, "invariant")do { if (!(jdk_jfr_module != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 435, "assert(" "jdk_jfr_module != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
436 | if (java_base_module->can_read(jdk_jfr_module)) { |
437 | can_read = true; |
438 | } |
439 | return can_read; |
440 | } |
441 | |
442 | static const char registered_constant[] = "Ljdk/jfr/Registered;"; |
443 | |
444 | // Evaluate to the value of the first found "Ljdk/jfr/Registered;" annotation. |
445 | // Searching moves upwards in the klass hierarchy in order to support |
446 | // inherited annotations in addition to the ability to override. |
447 | static bool should_register_klass(const InstanceKlass* ik, bool& untypedEventHandler) { |
448 | assert(ik != NULL, "invariant")do { if (!(ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 448, "assert(" "ik != __null" ") failed", "invariant"); ::breakpoint (); } } while (0); |
449 | assert(JdkJfrEvent::is_a(ik), "invariant")do { if (!(JdkJfrEvent::is_a(ik))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 449, "assert(" "JdkJfrEvent::is_a(ik)" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
450 | assert(!untypedEventHandler, "invariant")do { if (!(!untypedEventHandler)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 450, "assert(" "!untypedEventHandler" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
451 | static const Symbol* registered_symbol = NULL__null; |
452 | if (registered_symbol == NULL__null) { |
453 | registered_symbol = SymbolTable::probe(registered_constant, sizeof registered_constant - 1); |
454 | if (registered_symbol == NULL__null) { |
455 | untypedEventHandler = true; |
456 | return false; |
457 | } |
458 | } |
459 | assert(registered_symbol != NULL, "invariant")do { if (!(registered_symbol != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 459, "assert(" "registered_symbol != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
460 | bool value = false; // to be set by annotation_value |
461 | untypedEventHandler = !(annotation_value(ik, registered_symbol, value) || java_base_can_read_jdk_jfr()); |
462 | return value; |
463 | } |
464 | |
465 | /* |
466 | * Map an utf8 constant back to its CONSTANT_UTF8_INFO |
467 | */ |
468 | static u2 utf8_info_index(const InstanceKlass* ik, const Symbol* const target, TRAPSJavaThread* __the_thread__) { |
469 | assert(target != NULL, "invariant")do { if (!(target != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 469, "assert(" "target != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); |
470 | const ConstantPool* cp = ik->constants(); |
471 | const int cp_len = cp->length(); |
472 | for (u2 index = 1; index < cp_len; ++index) { |
473 | const constantTag tag = cp->tag_at(index); |
474 | if (tag.is_utf8()) { |
475 | const Symbol* const utf8_sym = cp->symbol_at(index); |
476 | assert(utf8_sym != NULL, "invariant")do { if (!(utf8_sym != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 476, "assert(" "utf8_sym != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
477 | if (utf8_sym == target) { |
478 | return index; |
479 | } |
480 | } |
481 | } |
482 | // not in constant pool |
483 | return invalid_cp_index; |
484 | } |
485 | |
486 | #ifdef ASSERT1 |
487 | static bool is_index_within_range(u2 index, u2 orig_cp_len, u2 new_cp_entries_len) { |
488 | return index > 0 && index < orig_cp_len + new_cp_entries_len; |
489 | } |
490 | #endif |
491 | |
492 | static u2 add_utf8_info(JfrBigEndianWriter& writer, const char* utf8_constant, u2 orig_cp_len, u2& new_cp_entries_len) { |
493 | assert(utf8_constant != NULL, "invariant")do { if (!(utf8_constant != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 493, "assert(" "utf8_constant != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
494 | writer.write<u1>(JVM_CONSTANT_Utf8); |
495 | writer.write_utf8_u2_len(utf8_constant); |
496 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 496, "assert(" "writer.is_valid()" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
497 | // return index for the added utf8 info |
498 | return orig_cp_len + new_cp_entries_len++; |
499 | } |
500 | |
501 | static u2 add_method_ref_info(JfrBigEndianWriter& writer, |
502 | u2 cls_name_index, |
503 | u2 method_index, |
504 | u2 desc_index, |
505 | u2 orig_cp_len, |
506 | u2& number_of_new_constants, |
507 | TRAPSJavaThread* __the_thread__) { |
508 | assert(cls_name_index != invalid_cp_index, "invariant")do { if (!(cls_name_index != invalid_cp_index)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 508, "assert(" "cls_name_index != invalid_cp_index" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
509 | assert(method_index != invalid_cp_index, "invariant")do { if (!(method_index != invalid_cp_index)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 509, "assert(" "method_index != invalid_cp_index" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
510 | assert(desc_index != invalid_cp_index, "invariant")do { if (!(desc_index != invalid_cp_index)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 510, "assert(" "desc_index != invalid_cp_index" ") failed", "invariant"); ::breakpoint(); } } while (0); |
511 | assert(is_index_within_range(cls_name_index, orig_cp_len, number_of_new_constants), "invariant")do { if (!(is_index_within_range(cls_name_index, orig_cp_len, number_of_new_constants))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 511, "assert(" "is_index_within_range(cls_name_index, orig_cp_len, number_of_new_constants)" ") failed", "invariant"); ::breakpoint(); } } while (0); |
512 | assert(is_index_within_range(method_index, orig_cp_len, number_of_new_constants), "invariant")do { if (!(is_index_within_range(method_index, orig_cp_len, number_of_new_constants ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 512, "assert(" "is_index_within_range(method_index, orig_cp_len, number_of_new_constants)" ") failed", "invariant"); ::breakpoint(); } } while (0); |
513 | assert(is_index_within_range(desc_index, orig_cp_len, number_of_new_constants), "invariant")do { if (!(is_index_within_range(desc_index, orig_cp_len, number_of_new_constants ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 513, "assert(" "is_index_within_range(desc_index, orig_cp_len, number_of_new_constants)" ") failed", "invariant"); ::breakpoint(); } } while (0); |
514 | writer.write<u1>(JVM_CONSTANT_Class); |
515 | writer.write<u2>(cls_name_index); |
516 | const u2 cls_entry_index = orig_cp_len + number_of_new_constants; |
517 | ++number_of_new_constants; |
518 | writer.write<u1>(JVM_CONSTANT_NameAndType); |
519 | writer.write<u2>(method_index); |
520 | writer.write<u2>(desc_index); |
521 | const u2 nat_entry_index = orig_cp_len + number_of_new_constants; |
522 | ++number_of_new_constants; |
523 | writer.write<u1>(JVM_CONSTANT_Methodref); |
524 | writer.write<u2>(cls_entry_index); |
525 | writer.write<u2>(nat_entry_index); |
526 | // post-increment number_of_new_constants |
527 | // value returned is the index to the added method_ref |
528 | return orig_cp_len + number_of_new_constants++; |
529 | } |
530 | |
531 | static u2 add_flr_register_method_constants(JfrBigEndianWriter& writer, |
532 | const u2* utf8_indexes, |
533 | u2 orig_cp_len, |
534 | u2& number_of_new_constants, |
535 | TRAPSJavaThread* __the_thread__) { |
536 | assert(utf8_indexes != NULL, "invariant")do { if (!(utf8_indexes != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 536, "assert(" "utf8_indexes != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
537 | return add_method_ref_info(writer, |
538 | utf8_indexes[UTF8_OPT_FlightRecorder], |
539 | utf8_indexes[UTF8_OPT_register], |
540 | utf8_indexes[UTF8_OPT_CLASS_VOID_METHOD_DESC], |
541 | orig_cp_len, |
542 | number_of_new_constants, |
543 | THREAD__the_thread__); |
544 | } |
545 | |
546 | /* |
547 | * field_info { |
548 | * u2 access_flags; |
549 | * u2 name_index; |
550 | * u2 descriptor_index; |
551 | * u2 attributes_count; |
552 | * attribute_info attributes[attributes_count]; |
553 | * } |
554 | */ |
555 | static jlong add_field_info(JfrBigEndianWriter& writer, u2 name_index, u2 desc_index, bool is_static = false) { |
556 | assert(name_index != invalid_cp_index, "invariant")do { if (!(name_index != invalid_cp_index)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 556, "assert(" "name_index != invalid_cp_index" ") failed", "invariant"); ::breakpoint(); } } while (0); |
557 | assert(desc_index != invalid_cp_index, "invariant")do { if (!(desc_index != invalid_cp_index)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 557, "assert(" "desc_index != invalid_cp_index" ") failed", "invariant"); ::breakpoint(); } } while (0); |
558 | DEBUG_ONLY(const jlong start_offset = writer.current_offset();)const jlong start_offset = writer.current_offset(); |
559 | writer.write<u2>(JVM_ACC_SYNTHETIC | JVM_ACC_PRIVATE | (is_static ? JVM_ACC_STATIC : JVM_ACC_TRANSIENT)); // flags |
560 | writer.write(name_index); |
561 | writer.write(desc_index); |
562 | writer.write((u2)0x0); // attributes_count |
563 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 563, "assert(" "writer.is_valid()" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
564 | DEBUG_ONLY(assert(start_offset + 8 == writer.current_offset(), "invariant");)do { if (!(start_offset + 8 == writer.current_offset())) { (* g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 564, "assert(" "start_offset + 8 == writer.current_offset()" ") failed", "invariant"); ::breakpoint(); } } while (0); |
565 | return writer.current_offset(); |
566 | } |
567 | |
568 | static u2 add_field_infos(JfrBigEndianWriter& writer, const u2* utf8_indexes, bool untypedEventHandler) { |
569 | assert(utf8_indexes != NULL, "invariant")do { if (!(utf8_indexes != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 569, "assert(" "utf8_indexes != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
570 | add_field_info(writer, |
571 | utf8_indexes[UTF8_REQ_eventHandler], |
572 | untypedEventHandler ? utf8_indexes[UTF8_OPT_LjavaLangObject] : utf8_indexes[UTF8_OPT_eventHandler_FIELD_DESC], |
573 | true); // static |
574 | |
575 | add_field_info(writer, |
576 | utf8_indexes[UTF8_REQ_startTime], |
577 | utf8_indexes[UTF8_REQ_J_FIELD_DESC]); |
578 | |
579 | add_field_info(writer, |
580 | utf8_indexes[UTF8_REQ_duration], |
581 | utf8_indexes[UTF8_REQ_J_FIELD_DESC]); |
582 | |
583 | return number_of_new_fields; |
584 | } |
585 | |
586 | /* |
587 | * method_info { |
588 | * u2 access_flags; |
589 | * u2 name_index; |
590 | * u2 descriptor_index; |
591 | * u2 attributes_count; |
592 | * attribute_info attributes[attributes_count]; |
593 | * } |
594 | * |
595 | * Code_attribute { |
596 | * u2 attribute_name_index; |
597 | * u4 attribute_length; |
598 | * u2 max_stack; |
599 | * u2 max_locals; |
600 | * u4 code_length; |
601 | * u1 code[code_length]; |
602 | * u2 exception_table_length; |
603 | * { u2 start_pc; |
604 | * u2 end_pc; |
605 | * u2 handler_pc; |
606 | * u2 catch_type; |
607 | * } exception_table[exception_table_length]; |
608 | * u2 attributes_count; |
609 | * attribute_info attributes[attributes_count]; |
610 | * } |
611 | */ |
612 | |
613 | static jlong add_method_info(JfrBigEndianWriter& writer, |
614 | u2 name_index, |
615 | u2 desc_index, |
616 | u2 code_index, |
617 | const u1* const code, |
618 | const size_t code_len) { |
619 | assert(name_index > 0, "invariant")do { if (!(name_index > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 619, "assert(" "name_index > 0" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
620 | assert(desc_index > 0, "invariant")do { if (!(desc_index > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 620, "assert(" "desc_index > 0" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
621 | assert(code_index > 0, "invariant")do { if (!(code_index > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 621, "assert(" "code_index > 0" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
622 | DEBUG_ONLY(const jlong start_offset = writer.current_offset();)const jlong start_offset = writer.current_offset(); |
623 | writer.write<u2>(JVM_ACC_SYNTHETIC | JVM_ACC_PUBLIC); // flags |
624 | writer.write(name_index); |
625 | writer.write(desc_index); |
626 | writer.write<u2>(0x1); // attributes_count ; 1 for "Code" attribute |
627 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 627, "assert(" "writer.is_valid()" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
628 | DEBUG_ONLY(assert(start_offset + 8 == writer.current_offset(), "invariant");)do { if (!(start_offset + 8 == writer.current_offset())) { (* g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 628, "assert(" "start_offset + 8 == writer.current_offset()" ") failed", "invariant"); ::breakpoint(); } } while (0); |
629 | // Code attribute |
630 | writer.write(code_index); // "Code" |
631 | writer.write_bytes(code, code_len); |
632 | DEBUG_ONLY(assert((start_offset + 8 + 2 + (jlong)code_len) == writer.current_offset(), "invariant");)do { if (!((start_offset + 8 + 2 + (jlong)code_len) == writer .current_offset())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 632, "assert(" "(start_offset + 8 + 2 + (jlong)code_len) == writer.current_offset()" ") failed", "invariant"); ::breakpoint(); } } while (0); |
633 | return writer.current_offset(); |
634 | } |
635 | |
636 | /* |
637 | * On return, the passed stream will be positioned |
638 | * just after the constant pool section in the classfile |
639 | * and the cp length is returned. |
640 | * |
641 | * Stream should come in at the start position. |
642 | */ |
643 | static u2 position_stream_after_cp(const ClassFileStream* stream) { |
644 | assert(stream != NULL, "invariant")do { if (!(stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 644, "assert(" "stream != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); |
645 | assert(stream->current_offset() == 0, "invariant")do { if (!(stream->current_offset() == 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 645, "assert(" "stream->current_offset() == 0" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
646 | stream->skip_u4_fast(2); // 8 bytes skipped |
647 | const u2 cp_len = stream->get_u2_fast(); |
648 | assert(cp_len > 0, "invariant")do { if (!(cp_len > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 648, "assert(" "cp_len > 0" ") failed", "invariant"); :: breakpoint(); } } while (0); |
649 | // now spin the stream position to just after the constant pool |
650 | for (u2 index = 1; index < cp_len; ++index) { |
651 | const u1 tag = stream->get_u1_fast(); // cp tag |
652 | switch (tag) { |
653 | case JVM_CONSTANT_Class: |
654 | case JVM_CONSTANT_String: { |
655 | stream->skip_u2_fast(1); // skip 2 bytes |
656 | continue; |
657 | } |
658 | case JVM_CONSTANT_Fieldref: |
659 | case JVM_CONSTANT_Methodref: |
660 | case JVM_CONSTANT_InterfaceMethodref: |
661 | case JVM_CONSTANT_Integer: |
662 | case JVM_CONSTANT_Float: |
663 | case JVM_CONSTANT_NameAndType: |
664 | case JVM_CONSTANT_InvokeDynamic: { |
665 | stream->skip_u4_fast(1); // skip 4 bytes |
666 | continue; |
667 | } |
668 | case JVM_CONSTANT_Long: |
669 | case JVM_CONSTANT_Double: { |
670 | stream->skip_u4_fast(2); // skip 8 bytes |
671 | // Skip entry following eigth-byte constant, see JVM book p. 98 |
672 | ++index; |
673 | continue; |
674 | } |
675 | case JVM_CONSTANT_Utf8: { |
676 | u2 utf8_length = stream->get_u2_fast(); |
677 | stream->skip_u1_fast(utf8_length); // skip 2 + len bytes |
678 | continue; |
679 | } |
680 | case JVM_CONSTANT_MethodHandle: |
681 | case JVM_CONSTANT_MethodType: { |
682 | if (tag == JVM_CONSTANT_MethodHandle) { |
683 | stream->skip_u1_fast(1); |
684 | stream->skip_u2_fast(1); // skip 3 bytes |
685 | } |
686 | else if (tag == JVM_CONSTANT_MethodType) { |
687 | stream->skip_u2_fast(1); // skip 3 bytes |
688 | } |
689 | } |
690 | continue; |
691 | case JVM_CONSTANT_Dynamic: |
692 | stream->skip_u2_fast(1); |
693 | stream->skip_u2_fast(1); |
694 | continue; |
695 | default: |
696 | assert(false, "error in skip logic!")do { if (!(false)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 696, "assert(" "false" ") failed", "error in skip logic!"); ::breakpoint(); } } while (0); |
697 | break; |
698 | } // end switch(tag) |
699 | } |
700 | return cp_len; |
701 | } |
702 | |
703 | /* |
704 | * On return, the passed stream will be positioned |
705 | * just after the fields section in the classfile |
706 | * and the number of fields will be returned. |
707 | * |
708 | * Stream should come in positioned just before fields_count |
709 | */ |
710 | static u2 position_stream_after_fields(const ClassFileStream* stream) { |
711 | assert(stream != NULL, "invariant")do { if (!(stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 711, "assert(" "stream != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); |
712 | assert(stream->current_offset() > 0, "invariant")do { if (!(stream->current_offset() > 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 712, "assert(" "stream->current_offset() > 0" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
713 | // fields len |
714 | const u2 orig_fields_len = stream->get_u2_fast(); |
715 | // fields |
716 | for (u2 i = 0; i < orig_fields_len; ++i) { |
717 | stream->skip_u2_fast(3); |
718 | const u2 attrib_info_len = stream->get_u2_fast(); |
719 | for (u2 j = 0; j < attrib_info_len; ++j) { |
720 | stream->skip_u2_fast(1); |
721 | const u4 attrib_len = stream->get_u4_fast(); |
722 | stream->skip_u1_fast(attrib_len); |
723 | } |
724 | } |
725 | return orig_fields_len; |
726 | } |
727 | |
728 | /* |
729 | * On return, the passed stream will be positioned |
730 | * just after the methods section in the classfile |
731 | * and the number of methods will be returned. |
732 | * |
733 | * Stream should come in positioned just before methods_count |
734 | */ |
735 | static u2 position_stream_after_methods(JfrBigEndianWriter& writer, |
736 | const ClassFileStream* stream, |
737 | const u2* utf8_indexes, |
738 | bool register_klass, |
739 | const Method* clinit_method, |
740 | u4& orig_method_len_offset) { |
741 | assert(stream != NULL, "invariant")do { if (!(stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 741, "assert(" "stream != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); |
742 | assert(stream->current_offset() > 0, "invariant")do { if (!(stream->current_offset() > 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 742, "assert(" "stream->current_offset() > 0" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
743 | assert(utf8_indexes != NULL, "invariant")do { if (!(utf8_indexes != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 743, "assert(" "utf8_indexes != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
744 | // We will come back to this location when we |
745 | // know how many methods there will be. |
746 | writer.reserve(sizeof(u2)); |
747 | const u2 orig_methods_len = stream->get_u2_fast(); |
748 | // Move copy position past original method_count |
749 | // in order to not copy the original count |
750 | orig_method_len_offset += sizeof(u2); |
751 | for (u2 i = 0; i < orig_methods_len; ++i) { |
752 | const u4 method_offset = stream->current_offset(); |
753 | stream->skip_u2_fast(1); // Access Flags |
754 | const u2 name_index = stream->get_u2_fast(); // Name index |
755 | stream->skip_u2_fast(1); // Descriptor index |
756 | const u2 attributes_count = stream->get_u2_fast(); |
757 | for (u2 j = 0; j < attributes_count; ++j) { |
758 | stream->skip_u2_fast(1); |
759 | const u4 attrib_len = stream->get_u4_fast(); |
760 | stream->skip_u1_fast(attrib_len); |
761 | } |
762 | if (clinit_method != NULL__null && name_index == clinit_method->name_index()) { |
763 | // The method just parsed is an existing <clinit> method. |
764 | // If the class has the @Registered(false) annotation, i.e. marking a class |
765 | // for opting out from automatic registration, then we do not need to do anything. |
766 | if (!register_klass) { |
767 | continue; |
768 | } |
769 | // Automatic registration with the jfr system is acccomplished |
770 | // by pre-pending code to the <clinit> method of the class. |
771 | // We will need to re-create a new <clinit> in a later step. |
772 | // For now, ensure that this method is excluded from the methods |
773 | // being copied. |
774 | writer.write_bytes(stream->buffer() + orig_method_len_offset, |
775 | method_offset - orig_method_len_offset); |
776 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 776, "assert(" "writer.is_valid()" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
777 | |
778 | // Update copy position to skip copy of <clinit> method |
779 | orig_method_len_offset = stream->current_offset(); |
780 | } |
781 | } |
782 | return orig_methods_len; |
783 | } |
784 | |
785 | static u2 add_method_infos(JfrBigEndianWriter& writer, const u2* utf8_indexes) { |
786 | assert(utf8_indexes != NULL, "invariant")do { if (!(utf8_indexes != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 786, "assert(" "utf8_indexes != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
787 | add_method_info(writer, |
788 | utf8_indexes[UTF8_REQ_begin], |
789 | utf8_indexes[UTF8_REQ_EMPTY_VOID_METHOD_DESC], |
790 | utf8_indexes[UTF8_REQ_Code], |
791 | empty_void_method_code_attribute, |
792 | sizeof(empty_void_method_code_attribute)); |
793 | |
794 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 794, "assert(" "writer.is_valid()" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
795 | |
796 | add_method_info(writer, |
797 | utf8_indexes[UTF8_REQ_end], |
798 | utf8_indexes[UTF8_REQ_EMPTY_VOID_METHOD_DESC], |
799 | utf8_indexes[UTF8_REQ_Code], |
800 | empty_void_method_code_attribute, |
801 | sizeof(empty_void_method_code_attribute)); |
802 | |
803 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 803, "assert(" "writer.is_valid()" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
804 | |
805 | add_method_info(writer, |
806 | utf8_indexes[UTF8_REQ_commit], |
807 | utf8_indexes[UTF8_REQ_EMPTY_VOID_METHOD_DESC], |
808 | utf8_indexes[UTF8_REQ_Code], |
809 | empty_void_method_code_attribute, |
810 | sizeof(empty_void_method_code_attribute)); |
811 | |
812 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 812, "assert(" "writer.is_valid()" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
813 | |
814 | add_method_info(writer, |
815 | utf8_indexes[UTF8_REQ_isEnabled], |
816 | utf8_indexes[UTF8_REQ_EMPTY_BOOLEAN_METHOD_DESC], |
817 | utf8_indexes[UTF8_REQ_Code], |
818 | boolean_method_code_attribute, |
819 | sizeof(boolean_method_code_attribute)); |
820 | |
821 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 821, "assert(" "writer.is_valid()" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
822 | |
823 | add_method_info(writer, |
824 | utf8_indexes[UTF8_REQ_shouldCommit], |
825 | utf8_indexes[UTF8_REQ_EMPTY_BOOLEAN_METHOD_DESC], |
826 | utf8_indexes[UTF8_REQ_Code], |
827 | boolean_method_code_attribute, |
828 | sizeof(boolean_method_code_attribute)); |
829 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 829, "assert(" "writer.is_valid()" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
830 | return number_of_new_methods; |
831 | } |
832 | |
833 | static void adjust_exception_table(JfrBigEndianWriter& writer, u2 bci_adjustment_offset, const Method* method, TRAPSJavaThread* __the_thread__) { |
834 | const u2 ex_table_length = method != NULL__null ? (u2)method->exception_table_length() : 0; |
835 | writer.write<u2>(ex_table_length); // Exception table length |
836 | if (ex_table_length > 0) { |
837 | assert(method != NULL, "invariant")do { if (!(method != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 837, "assert(" "method != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); |
838 | const ExceptionTableElement* const ex_elements = method->exception_table_start(); |
839 | for (int i = 0; i < ex_table_length; ++i) { |
840 | assert(ex_elements != NULL, "invariant")do { if (!(ex_elements != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 840, "assert(" "ex_elements != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
841 | writer.write<u2>(ex_elements[i].start_pc + bci_adjustment_offset); |
842 | writer.write<u2>(ex_elements[i].end_pc + bci_adjustment_offset); |
843 | writer.write<u2>(ex_elements[i].handler_pc + bci_adjustment_offset); |
844 | writer.write<u2>(ex_elements[i].catch_type_index); // no adjustment |
845 | } |
846 | } |
847 | } |
848 | |
849 | enum StackMapFrameTypes { |
850 | SAME_FRAME_BEGIN = 0, |
851 | SAME_FRAME_END = 63, |
852 | SAME_LOCALS_1_STACK_ITEM_FRAME_BEGIN = 64, |
853 | SAME_LOCALS_1_STACK_ITEM_FRAME_END = 127, |
854 | SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247, |
855 | CHOP_FRAME_BEGIN = 248, |
856 | CHOP_FRAME_END = 250, |
857 | SAME_FRAME_EXTENDED = 251, |
858 | APPEND_FRAME_BEGIN = 252, |
859 | APPEND_FRAME_END = 254, |
860 | FULL_FRAME = 255 |
861 | }; |
862 | |
863 | static void adjust_stack_map(JfrBigEndianWriter& writer, |
864 | Array<u1>* stack_map, |
865 | const u2* utf8_indexes, |
866 | u2 bci_adjustment_offset, |
867 | TRAPSJavaThread* __the_thread__) { |
868 | assert(stack_map != NULL, "invariant")do { if (!(stack_map != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 868, "assert(" "stack_map != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
869 | assert(utf8_indexes != NULL, "invariant")do { if (!(utf8_indexes != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 869, "assert(" "utf8_indexes != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
870 | writer.write<u2>(utf8_indexes[UTF8_OPT_StackMapTable]); |
871 | const jlong stack_map_attrib_len_offset = writer.current_offset(); |
872 | writer.reserve(sizeof(u4)); |
873 | StackMapStream stream(stack_map); |
874 | const u2 stack_map_entries = stream.get_u2(THREAD__the_thread__); |
875 | // number of entries |
876 | writer.write<u2>(stack_map_entries); // new stack map entry added |
877 | const u1 frame_type = stream.get_u1(THREAD__the_thread__); |
878 | // SAME_FRAME and SAME_LOCALS_1_STACK_ITEM_FRAME encode |
879 | // their offset_delta into the actual frame type itself. |
880 | // If such a frame type is the first frame, then we transform |
881 | // it to a SAME_FRAME_EXTENDED or a SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED frame. |
882 | // This is done in order to not overflow frame types accidentally |
883 | // when adjusting the offset_delta. In changing the frame types, |
884 | // we can work with an explicit u2 offset_delta field (like the other frame types) |
885 | if (frame_type <= SAME_FRAME_END) { |
886 | writer.write<u1>(SAME_FRAME_EXTENDED); |
887 | writer.write<u2>(frame_type + bci_adjustment_offset); |
888 | } else if (frame_type >= SAME_LOCALS_1_STACK_ITEM_FRAME_BEGIN && |
889 | frame_type <= SAME_LOCALS_1_STACK_ITEM_FRAME_END) { |
890 | writer.write<u1>(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED); |
891 | writer.write<u2>((frame_type - SAME_LOCALS_1_STACK_ITEM_FRAME_BEGIN) + bci_adjustment_offset); |
892 | } else if (frame_type >= SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { |
893 | // SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED to FULL_FRAME |
894 | // has a u2 offset_delta field |
895 | writer.write<u1>(frame_type); |
896 | writer.write<u2>(stream.get_u2(THREAD__the_thread__) + bci_adjustment_offset); |
897 | } else { |
898 | assert(false, "stackMapFrame type is invalid")do { if (!(false)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 898, "assert(" "false" ") failed", "stackMapFrame type is invalid" ); ::breakpoint(); } } while (0); |
899 | } |
900 | |
901 | while (!stream.at_end()) { |
902 | writer.write<u1>(stream.get_u1(THREAD__the_thread__)); |
903 | } |
904 | |
905 | u4 stack_map_attrib_len = writer.current_offset() - stack_map_attrib_len_offset; |
906 | // the stack_map_table_attributes_length value is exclusive |
907 | stack_map_attrib_len -= sizeof(u4); |
908 | writer.write_at_offset(stack_map_attrib_len, stack_map_attrib_len_offset); |
909 | } |
910 | |
911 | static void adjust_line_number_table(JfrBigEndianWriter& writer, |
912 | const u2* utf8_indexes, |
913 | u4 bci_adjustement_offset, |
914 | const Method* method, |
915 | TRAPSJavaThread* __the_thread__) { |
916 | assert(utf8_indexes != NULL, "invariant")do { if (!(utf8_indexes != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 916, "assert(" "utf8_indexes != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
917 | assert(method != NULL, "invariant")do { if (!(method != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 917, "assert(" "method != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); |
918 | assert(method->has_linenumber_table(), "invariant")do { if (!(method->has_linenumber_table())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 918, "assert(" "method->has_linenumber_table()" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
919 | writer.write(utf8_indexes[UTF8_OPT_LineNumberTable]); |
920 | const jlong lnt_attributes_length_offset = writer.current_offset(); |
921 | writer.reserve(sizeof(u4)); |
922 | const jlong lnt_attributes_entries_offset = writer.current_offset(); |
923 | writer.reserve(sizeof(u2)); |
924 | u1* lnt = method->compressed_linenumber_table(); |
925 | CompressedLineNumberReadStream lnt_stream(lnt); |
926 | u2 line_number_table_entries = 0; |
927 | while (lnt_stream.read_pair()) { |
928 | ++line_number_table_entries; |
929 | const u2 bci = (u2)lnt_stream.bci(); |
930 | writer.write<u2>(bci + (u2)bci_adjustement_offset); |
931 | writer.write<u2>((u2)lnt_stream.line()); |
932 | } |
933 | writer.write_at_offset(line_number_table_entries, lnt_attributes_entries_offset); |
934 | u4 lnt_table_attributes_len = writer.current_offset() - lnt_attributes_length_offset; |
935 | // the line_number_table_attributes_length value is exclusive |
936 | lnt_table_attributes_len -= sizeof(u4); |
937 | writer.write_at_offset(lnt_table_attributes_len, lnt_attributes_length_offset); |
938 | } |
939 | |
940 | // returns the number of lvtt entries |
941 | static u2 adjust_local_variable_table(JfrBigEndianWriter& writer, |
942 | const u2* utf8_indexes, |
943 | u2 bci_adjustment_offset, |
944 | const Method* method, |
945 | TRAPSJavaThread* __the_thread__) { |
946 | assert(utf8_indexes != NULL, "invariant")do { if (!(utf8_indexes != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 946, "assert(" "utf8_indexes != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
947 | assert(method != NULL, "invariant")do { if (!(method != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 947, "assert(" "method != __null" ") failed", "invariant"); ::breakpoint(); } } while (0); |
948 | assert(method->has_localvariable_table(), "invariant")do { if (!(method->has_localvariable_table())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 948, "assert(" "method->has_localvariable_table()" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
949 | writer.write<u2>(utf8_indexes[UTF8_OPT_LocalVariableTable]); |
950 | const jlong lvt_attributes_length_offset = writer.current_offset(); |
951 | writer.reserve(sizeof(u4)); |
952 | const int lvt_len = method->localvariable_table_length(); |
953 | writer.write<u2>((u2)lvt_len); |
954 | const LocalVariableTableElement* table = method->localvariable_table_start(); |
955 | assert(table != NULL, "invariant")do { if (!(table != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 955, "assert(" "table != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
956 | u2 num_lvtt_entries = 0; |
957 | for (int i = 0; i < lvt_len; ++i) { |
958 | writer.write<u2>(table[i].start_bci + bci_adjustment_offset); |
959 | writer.write<u2>(table[i].length); |
960 | writer.write<u2>(table[i].name_cp_index); |
961 | writer.write<u2>(table[i].descriptor_cp_index); |
962 | writer.write<u2>(table[i].slot); |
963 | if (table[i].signature_cp_index > 0) { |
964 | ++num_lvtt_entries; |
965 | } |
966 | } |
967 | u4 lvt_table_attributes_len = writer.current_offset() - lvt_attributes_length_offset; |
968 | // the lvt_table_attributes_length value is exclusive |
969 | lvt_table_attributes_len -= sizeof(u4); |
970 | writer.write_at_offset(lvt_table_attributes_len, lvt_attributes_length_offset); |
971 | return num_lvtt_entries; |
972 | } |
973 | |
974 | static void adjust_local_variable_type_table(JfrBigEndianWriter& writer, |
975 | const u2* utf8_indexes, |
976 | u2 bci_adjustment_offset, |
977 | u2 num_lvtt_entries, |
978 | const Method* method, |
979 | TRAPSJavaThread* __the_thread__) { |
980 | assert(num_lvtt_entries > 0, "invariant")do { if (!(num_lvtt_entries > 0)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 980, "assert(" "num_lvtt_entries > 0" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
981 | writer.write<u2>(utf8_indexes[UTF8_OPT_LocalVariableTypeTable]); |
982 | const jlong lvtt_attributes_length_offset = writer.current_offset(); |
983 | writer.reserve(sizeof(u4)); |
984 | writer.write<u2>(num_lvtt_entries); |
985 | const LocalVariableTableElement* table = method->localvariable_table_start(); |
986 | assert(table != NULL, "invariant")do { if (!(table != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 986, "assert(" "table != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
987 | const int lvt_len = method->localvariable_table_length(); |
988 | for (int i = 0; i < lvt_len; ++i) { |
989 | if (table[i].signature_cp_index > 0) { |
990 | writer.write<u2>(table[i].start_bci + bci_adjustment_offset); |
991 | writer.write<u2>(table[i].length); |
992 | writer.write<u2>(table[i].name_cp_index); |
993 | writer.write<u2>(table[i].signature_cp_index); |
994 | writer.write<u2>(table[i].slot); |
995 | } |
996 | } |
997 | u4 lvtt_table_attributes_len = writer.current_offset() - lvtt_attributes_length_offset; |
998 | // the lvtt_table_attributes_length value is exclusive |
999 | lvtt_table_attributes_len -= sizeof(u4); |
1000 | writer.write_at_offset(lvtt_table_attributes_len, lvtt_attributes_length_offset); |
1001 | } |
1002 | |
1003 | static void adjust_code_attributes(JfrBigEndianWriter& writer, |
1004 | const u2* utf8_indexes, |
1005 | u2 bci_adjustment_offset, |
1006 | const Method* clinit_method, |
1007 | TRAPSJavaThread* __the_thread__) { |
1008 | // "Code" attributes |
1009 | assert(utf8_indexes != NULL, "invariant")do { if (!(utf8_indexes != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1009, "assert(" "utf8_indexes != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1010 | const jlong code_attributes_offset = writer.current_offset(); |
1011 | writer.reserve(sizeof(u2)); |
1012 | u2 number_of_code_attributes = 0; |
1013 | if (clinit_method != NULL__null) { |
1014 | Array<u1>* stack_map = clinit_method->stackmap_data(); |
1015 | if (stack_map != NULL__null) { |
1016 | ++number_of_code_attributes; |
1017 | adjust_stack_map(writer, stack_map, utf8_indexes, bci_adjustment_offset, THREAD__the_thread__); |
1018 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1018, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1019 | } |
1020 | if (clinit_method != NULL__null && clinit_method->has_linenumber_table()) { |
1021 | ++number_of_code_attributes; |
1022 | adjust_line_number_table(writer, utf8_indexes, bci_adjustment_offset, clinit_method, THREAD__the_thread__); |
1023 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1023, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1024 | } |
1025 | if (clinit_method != NULL__null && clinit_method->has_localvariable_table()) { |
1026 | ++number_of_code_attributes; |
1027 | const u2 num_of_lvtt_entries = adjust_local_variable_table(writer, utf8_indexes, bci_adjustment_offset, clinit_method, THREAD__the_thread__); |
1028 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1028, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1029 | if (num_of_lvtt_entries > 0) { |
1030 | ++number_of_code_attributes; |
1031 | adjust_local_variable_type_table(writer, utf8_indexes, bci_adjustment_offset, num_of_lvtt_entries, clinit_method, THREAD__the_thread__); |
1032 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1032, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1033 | } |
1034 | } |
1035 | } |
1036 | |
1037 | // Store the number of code_attributes |
1038 | writer.write_at_offset(number_of_code_attributes, code_attributes_offset); |
1039 | } |
1040 | |
1041 | static jlong insert_clinit_method(const InstanceKlass* ik, |
1042 | const ClassFileParser& parser, |
1043 | JfrBigEndianWriter& writer, |
1044 | u2 orig_constant_pool_len, |
1045 | const u2* utf8_indexes, |
1046 | const u2 register_method_ref_index, |
1047 | const Method* clinit_method, |
1048 | TRAPSJavaThread* __the_thread__) { |
1049 | assert(utf8_indexes != NULL, "invariant")do { if (!(utf8_indexes != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1049, "assert(" "utf8_indexes != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1050 | // The injected code length is always this value. |
1051 | // This is to ensure that padding can be done |
1052 | // where needed and to simplify size calculations. |
1053 | static const u2 injected_code_length = 8; |
1054 | const u2 name_index = utf8_indexes[UTF8_OPT_clinit]; |
1055 | assert(name_index != invalid_cp_index, "invariant")do { if (!(name_index != invalid_cp_index)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1055, "assert(" "name_index != invalid_cp_index" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
1056 | const u2 desc_index = utf8_indexes[UTF8_REQ_EMPTY_VOID_METHOD_DESC]; |
1057 | const u2 max_stack = MAX2(clinit_method != NULL__null ? clinit_method->verifier_max_stack() : 1, 1); |
1058 | const u2 max_locals = MAX2(clinit_method != NULL__null ? clinit_method->max_locals() : 0, 0); |
1059 | const u2 orig_bytecodes_length = clinit_method != NULL__null ? (u2)clinit_method->code_size() : 0; |
1060 | const address orig_bytecodes = clinit_method != NULL__null ? clinit_method->code_base() : NULL__null; |
1061 | const u2 new_code_length = injected_code_length + orig_bytecodes_length; |
1062 | DEBUG_ONLY(const jlong start_offset = writer.current_offset();)const jlong start_offset = writer.current_offset(); |
1063 | writer.write<u2>(JVM_ACC_STATIC); // flags |
1064 | writer.write<u2>(name_index); |
1065 | writer.write<u2>(desc_index); |
1066 | writer.write<u2>((u2)0x1); // attributes_count // "Code" |
1067 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1067, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1068 | DEBUG_ONLY(assert(start_offset + 8 == writer.current_offset(), "invariant");)do { if (!(start_offset + 8 == writer.current_offset())) { (* g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1068, "assert(" "start_offset + 8 == writer.current_offset()" ") failed", "invariant"); ::breakpoint(); } } while (0); |
1069 | // "Code" attribute |
1070 | writer.write<u2>(utf8_indexes[UTF8_REQ_Code]); // "Code" |
1071 | const jlong code_attribute_length_offset = writer.current_offset(); |
1072 | writer.reserve(sizeof(u4)); |
1073 | writer.write<u2>(max_stack); // max stack |
1074 | writer.write<u2>(max_locals); // max locals |
1075 | writer.write<u4>((u4)new_code_length); // code length |
1076 | |
1077 | /* BEGIN CLINIT CODE */ |
1078 | |
1079 | // Note the use of ldc_w here instead of ldc. |
1080 | // This is to handle all values of "this_class_index" |
1081 | writer.write<u1>((u1)Bytecodes::_ldc_w); |
1082 | writer.write<u2>((u2)parser.this_class_index()); // load constant "this class" |
1083 | writer.write<u1>((u1)Bytecodes::_invokestatic); |
1084 | // invoke "FlightRecorder.register(Ljava/lang/Class;") |
1085 | writer.write<u2>(register_method_ref_index); |
1086 | if (clinit_method == NULL__null) { |
1087 | writer.write<u1>((u1)Bytecodes::_nop); |
1088 | writer.write<u1>((u1)Bytecodes::_return); |
1089 | } else { |
1090 | // If we are pre-pending to original code, |
1091 | // do padding to minimize disruption to the original. |
1092 | // It might have dependencies on 4-byte boundaries |
1093 | // i.e. lookupswitch and tableswitch instructions |
1094 | writer.write<u1>((u1)Bytecodes::_nop); |
1095 | writer.write<u1>((u1)Bytecodes::_nop); |
1096 | // insert original clinit code |
1097 | writer.write_bytes(orig_bytecodes, orig_bytecodes_length); |
1098 | } |
1099 | |
1100 | /* END CLINIT CODE */ |
1101 | |
1102 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1102, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1103 | adjust_exception_table(writer, injected_code_length, clinit_method, THREAD__the_thread__); |
1104 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1104, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1105 | adjust_code_attributes(writer, utf8_indexes, injected_code_length, clinit_method, THREAD__the_thread__); |
1106 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1106, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1107 | u4 code_attribute_len = writer.current_offset() - code_attribute_length_offset; |
1108 | // the code_attribute_length value is exclusive |
1109 | code_attribute_len -= sizeof(u4); |
1110 | writer.write_at_offset(code_attribute_len, code_attribute_length_offset); |
1111 | return writer.current_offset(); |
1112 | } |
1113 | |
1114 | // Caller needs ResourceMark |
1115 | static ClassFileStream* create_new_bytes_for_event_klass(const InstanceKlass* ik, const ClassFileParser& parser, TRAPSJavaThread* __the_thread__) { |
1116 | DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD))JfrJavaSupport::check_java_thread_in_vm(__the_thread__); |
1117 | static const u2 public_final_flag_mask = JVM_ACC_PUBLIC | JVM_ACC_FINAL; |
1118 | const ClassFileStream* const orig_stream = parser.clone_stream(); |
1119 | const int orig_stream_length = orig_stream->length(); |
1120 | // allocate an identically sized buffer |
1121 | u1* const new_buffer = NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, u1, orig_stream_length)(u1*) resource_allocate_bytes(__the_thread__, (orig_stream_length ) * sizeof(u1), AllocFailStrategy::RETURN_NULL); |
1122 | if (new_buffer == NULL__null) { |
1123 | return NULL__null; |
1124 | } |
1125 | assert(new_buffer != NULL, "invariant")do { if (!(new_buffer != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1125, "assert(" "new_buffer != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1126 | // memcpy the entire [B |
1127 | memcpy(new_buffer, orig_stream->buffer(), orig_stream_length); |
1128 | const u2 orig_cp_len = position_stream_after_cp(orig_stream); |
1129 | assert(orig_cp_len > 0, "invariant")do { if (!(orig_cp_len > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1129, "assert(" "orig_cp_len > 0" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1130 | assert(orig_stream->current_offset() > 0, "invariant")do { if (!(orig_stream->current_offset() > 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1130, "assert(" "orig_stream->current_offset() > 0" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
1131 | orig_stream->skip_u2_fast(3); // access_flags, this_class_index, super_class_index |
1132 | const u2 iface_len = orig_stream->get_u2_fast(); |
1133 | orig_stream->skip_u2_fast(iface_len); |
1134 | // fields len |
1135 | const u2 orig_fields_len = orig_stream->get_u2_fast(); |
1136 | // fields |
1137 | for (u2 i = 0; i < orig_fields_len; ++i) { |
1138 | orig_stream->skip_u2_fast(3); |
1139 | const u2 attrib_info_len = orig_stream->get_u2_fast(); |
1140 | for (u2 j = 0; j < attrib_info_len; ++j) { |
1141 | orig_stream->skip_u2_fast(1); |
1142 | const u4 attrib_len = orig_stream->get_u4_fast(); |
1143 | orig_stream->skip_u1_fast(attrib_len); |
1144 | } |
1145 | } |
1146 | // methods |
1147 | const u2 orig_methods_len = orig_stream->get_u2_fast(); |
1148 | for (u2 i = 0; i < orig_methods_len; ++i) { |
1149 | const u4 access_flag_offset = orig_stream->current_offset(); |
1150 | const u2 flags = orig_stream->get_u2_fast(); |
1151 | // Rewrite JVM_ACC_FINAL -> JVM_ACC_PUBLIC |
1152 | if (public_final_flag_mask == flags) { |
1153 | JfrBigEndianWriter accessflagsrewriter(new_buffer + access_flag_offset, sizeof(u2)); |
1154 | accessflagsrewriter.write<u2>(JVM_ACC_PUBLIC); |
1155 | assert(accessflagsrewriter.is_valid(), "invariant")do { if (!(accessflagsrewriter.is_valid())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1155, "assert(" "accessflagsrewriter.is_valid()" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
1156 | } |
1157 | orig_stream->skip_u2_fast(2); |
1158 | const u2 attributes_count = orig_stream->get_u2_fast(); |
1159 | for (u2 j = 0; j < attributes_count; ++j) { |
1160 | orig_stream->skip_u2_fast(1); |
1161 | const u4 attrib_len = orig_stream->get_u4_fast(); |
1162 | orig_stream->skip_u1_fast(attrib_len); |
1163 | } |
1164 | } |
1165 | return new ClassFileStream(new_buffer, orig_stream_length, NULL__null, ClassFileStream::verify); |
1166 | } |
1167 | |
1168 | // Attempt to locate an existing UTF8_INFO mapping the utf8_constant. |
1169 | // If no UTF8_INFO exists, add (append) a new one to the constant pool. |
1170 | static u2 find_or_add_utf8_info(JfrBigEndianWriter& writer, |
1171 | const InstanceKlass* ik, |
1172 | const char* const utf8_constant, |
1173 | u2 orig_cp_len, |
1174 | u2& added_cp_entries, |
1175 | TRAPSJavaThread* __the_thread__) { |
1176 | assert(utf8_constant != NULL, "invariant")do { if (!(utf8_constant != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1176, "assert(" "utf8_constant != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1177 | TempNewSymbol utf8_sym = SymbolTable::new_symbol(utf8_constant); |
1178 | // lookup existing |
1179 | const int utf8_orig_idx = utf8_info_index(ik, utf8_sym, THREAD__the_thread__); |
1180 | if (utf8_orig_idx != invalid_cp_index) { |
1181 | // existing constant pool entry found |
1182 | return utf8_orig_idx; |
1183 | } |
1184 | // no existing match, need to add a new utf8 cp entry |
1185 | assert(invalid_cp_index == utf8_orig_idx, "invariant")do { if (!(invalid_cp_index == utf8_orig_idx)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1185, "assert(" "invalid_cp_index == utf8_orig_idx" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
1186 | // add / append new |
1187 | return add_utf8_info(writer, utf8_constant, orig_cp_len, added_cp_entries); |
1188 | } |
1189 | |
1190 | /* |
1191 | * This routine will resolve the required utf8_constants array |
1192 | * to their constant pool indexes (mapping to their UTF8_INFO's) |
1193 | * Only if a constant is actually needed and does not already exist |
1194 | * will it be added. |
1195 | * |
1196 | * The passed in indexes array will be populated with the resolved indexes. |
1197 | * The number of newly added constant pool entries is returned. |
1198 | */ |
1199 | static u2 resolve_utf8_indexes(JfrBigEndianWriter& writer, |
1200 | const InstanceKlass* ik, |
1201 | u2* const utf8_indexes, |
1202 | u2 orig_cp_len, |
1203 | const Method* clinit_method, |
1204 | bool register_klass, |
1205 | bool untypedEventHandler, |
1206 | TRAPSJavaThread* __the_thread__) { |
1207 | assert(utf8_indexes != NULL, "invariant")do { if (!(utf8_indexes != __null)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1207, "assert(" "utf8_indexes != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1208 | u2 added_cp_entries = 0; |
1209 | // resolve all required symbols |
1210 | for (u2 index = 0; index < NOF_UTF8_REQ_SYMBOLS; ++index) { |
1211 | utf8_indexes[index] = find_or_add_utf8_info(writer, ik, utf8_constants[index], orig_cp_len, added_cp_entries, THREAD__the_thread__); |
1212 | } |
1213 | |
1214 | // resolve optional constants |
1215 | utf8_indexes[UTF8_OPT_eventHandler_FIELD_DESC] = untypedEventHandler ? invalid_cp_index : |
1216 | find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_eventHandler_FIELD_DESC], orig_cp_len, added_cp_entries, THREAD__the_thread__); |
1217 | |
1218 | utf8_indexes[UTF8_OPT_LjavaLangObject] = untypedEventHandler ? |
1219 | find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_LjavaLangObject], orig_cp_len, added_cp_entries, THREAD__the_thread__) : invalid_cp_index; |
1220 | |
1221 | if (register_klass) { |
1222 | utf8_indexes[UTF8_OPT_clinit] = |
1223 | find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_clinit], orig_cp_len, added_cp_entries, THREAD__the_thread__); |
1224 | utf8_indexes[UTF8_OPT_FlightRecorder] = |
1225 | find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_FlightRecorder], orig_cp_len, added_cp_entries, THREAD__the_thread__); |
1226 | utf8_indexes[UTF8_OPT_register] = |
1227 | find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_register], orig_cp_len, added_cp_entries, THREAD__the_thread__); |
1228 | utf8_indexes[UTF8_OPT_CLASS_VOID_METHOD_DESC] = |
1229 | find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_CLASS_VOID_METHOD_DESC], orig_cp_len, added_cp_entries, THREAD__the_thread__); |
1230 | } else { |
1231 | utf8_indexes[UTF8_OPT_clinit] = invalid_cp_index; |
1232 | utf8_indexes[UTF8_OPT_FlightRecorder] = invalid_cp_index; |
1233 | utf8_indexes[UTF8_OPT_register] = invalid_cp_index; |
1234 | utf8_indexes[UTF8_OPT_CLASS_VOID_METHOD_DESC] = invalid_cp_index; |
1235 | } |
1236 | |
1237 | if (clinit_method != NULL__null && clinit_method->has_stackmap_table()) { |
1238 | utf8_indexes[UTF8_OPT_StackMapTable] = |
1239 | find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_StackMapTable], orig_cp_len, added_cp_entries, THREAD__the_thread__); |
1240 | } else { |
1241 | utf8_indexes[UTF8_OPT_StackMapTable] = invalid_cp_index; |
1242 | } |
1243 | |
1244 | if (clinit_method != NULL__null && clinit_method->has_linenumber_table()) { |
1245 | utf8_indexes[UTF8_OPT_LineNumberTable] = |
1246 | find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_LineNumberTable], orig_cp_len, added_cp_entries, THREAD__the_thread__); |
1247 | } else { |
1248 | utf8_indexes[UTF8_OPT_LineNumberTable] = invalid_cp_index; |
1249 | } |
1250 | |
1251 | if (clinit_method != NULL__null && clinit_method->has_localvariable_table()) { |
1252 | utf8_indexes[UTF8_OPT_LocalVariableTable] = |
1253 | find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_LocalVariableTable], orig_cp_len, added_cp_entries, THREAD__the_thread__); |
1254 | utf8_indexes[UTF8_OPT_LocalVariableTypeTable] = |
1255 | find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_LocalVariableTypeTable], orig_cp_len, added_cp_entries, THREAD__the_thread__); |
1256 | } else { |
1257 | utf8_indexes[UTF8_OPT_LocalVariableTable] = invalid_cp_index; |
1258 | utf8_indexes[UTF8_OPT_LocalVariableTypeTable] = invalid_cp_index; |
1259 | } |
1260 | |
1261 | return added_cp_entries; |
1262 | } |
1263 | |
1264 | static u1* new_bytes_for_lazy_instrumentation(const InstanceKlass* ik, |
1265 | const ClassFileParser& parser, |
1266 | jint& size_of_new_bytes, |
1267 | TRAPSJavaThread* __the_thread__) { |
1268 | assert(ik != NULL, "invariant")do { if (!(ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1268, "assert(" "ik != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1269 | // If the class already has a clinit method |
1270 | // we need to take that into account |
1271 | const Method* clinit_method = ik->class_initializer(); |
1272 | bool untypedEventHandler = false; |
1273 | const bool register_klass = should_register_klass(ik, untypedEventHandler); |
1274 | const ClassFileStream* const orig_stream = parser.clone_stream(); |
1275 | const int orig_stream_size = orig_stream->length(); |
1276 | assert(orig_stream->current_offset() == 0, "invariant")do { if (!(orig_stream->current_offset() == 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1276, "assert(" "orig_stream->current_offset() == 0" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
1277 | const u2 orig_cp_len = position_stream_after_cp(orig_stream); |
1278 | assert(orig_cp_len > 0, "invariant")do { if (!(orig_cp_len > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1278, "assert(" "orig_cp_len > 0" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1279 | assert(orig_stream->current_offset() > 0, "invariant")do { if (!(orig_stream->current_offset() > 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1279, "assert(" "orig_stream->current_offset() > 0" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
1280 | // Dimension and allocate a working byte buffer |
1281 | // to be used in building up a modified class [B. |
1282 | const jint new_buffer_size = extra_stream_bytes + orig_stream_size; |
1283 | u1* const new_buffer = NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, u1, new_buffer_size)(u1*) resource_allocate_bytes(__the_thread__, (new_buffer_size ) * sizeof(u1), AllocFailStrategy::RETURN_NULL); |
1284 | if (new_buffer == NULL__null) { |
1285 | log_error(jfr, system)(!(LogImpl<(LogTag::_jfr), (LogTag::_system), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_jfr), (LogTag::_system), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error> ("Thread local allocation (native) for " SIZE_FORMAT"%" "l" "u" |
1286 | " bytes failed in JfrClassAdapter::on_klass_creation", (size_t)new_buffer_size); |
1287 | return NULL__null; |
1288 | } |
1289 | assert(new_buffer != NULL, "invariant")do { if (!(new_buffer != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1289, "assert(" "new_buffer != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1290 | // [B wrapped in a big endian writer |
1291 | JfrBigEndianWriter writer(new_buffer, new_buffer_size); |
1292 | assert(writer.current_offset() == 0, "invariant")do { if (!(writer.current_offset() == 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1292, "assert(" "writer.current_offset() == 0" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1293 | const u4 orig_access_flag_offset = orig_stream->current_offset(); |
1294 | // Copy original stream from the beginning up to AccessFlags |
1295 | // This means the original constant pool contents are copied unmodified |
1296 | writer.write_bytes(orig_stream->buffer(), orig_access_flag_offset); |
1297 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1297, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1298 | assert(writer.current_offset() == (intptr_t)orig_access_flag_offset, "invariant")do { if (!(writer.current_offset() == (intptr_t)orig_access_flag_offset )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1298, "assert(" "writer.current_offset() == (intptr_t)orig_access_flag_offset" ") failed", "invariant"); ::breakpoint(); } } while (0); // same positions |
1299 | // Our writer now sits just after the last original constant pool entry. |
1300 | // I.e. we are in a good position to append new constant pool entries |
1301 | // This array will contain the resolved indexes |
1302 | // in order to reference UTF8_INFO's needed |
1303 | u2 utf8_indexes[NOF_UTF8_SYMBOLS]; |
1304 | // Resolve_utf8_indexes will be conservative in attempting to |
1305 | // locate an existing UTF8_INFO; it will only append constants |
1306 | // that is absolutely required |
1307 | u2 number_of_new_constants = |
1308 | resolve_utf8_indexes(writer, ik, utf8_indexes, orig_cp_len, clinit_method, register_klass, untypedEventHandler, THREAD__the_thread__); |
1309 | // UTF8_INFO entries now added to the constant pool |
1310 | // In order to invoke a method we would need additional |
1311 | // constants, JVM_CONSTANT_Class, JVM_CONSTANT_NameAndType |
1312 | // and JVM_CONSTANT_Methodref. |
1313 | const u2 flr_register_method_ref_index = |
1314 | register_klass ? |
1315 | add_flr_register_method_constants(writer, |
1316 | utf8_indexes, |
1317 | orig_cp_len, |
1318 | number_of_new_constants, |
1319 | THREAD__the_thread__) : invalid_cp_index; |
1320 | |
1321 | // New constant pool entries added and all UTF8_INFO indexes resolved |
1322 | // Now update the class file constant_pool_count with an updated count |
1323 | writer.write_at_offset<u2>(orig_cp_len + number_of_new_constants, 8); |
1324 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1324, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1325 | orig_stream->skip_u2_fast(3); // access_flags, this_class_index, super_class_index |
1326 | const u2 iface_len = orig_stream->get_u2_fast(); // interfaces |
1327 | orig_stream->skip_u2_fast(iface_len); |
1328 | const u4 orig_fields_len_offset = orig_stream->current_offset(); |
1329 | // Copy from AccessFlags up to and including interfaces |
1330 | writer.write_bytes(orig_stream->buffer() + orig_access_flag_offset, |
1331 | orig_fields_len_offset - orig_access_flag_offset); |
1332 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1332, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1333 | const jlong new_fields_len_offset = writer.current_offset(); |
1334 | const u2 orig_fields_len = position_stream_after_fields(orig_stream); |
1335 | u4 orig_method_len_offset = orig_stream->current_offset(); |
1336 | // Copy up to and including fields |
1337 | writer.write_bytes(orig_stream->buffer() + orig_fields_len_offset, orig_method_len_offset - orig_fields_len_offset); |
1338 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1338, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1339 | // We are sitting just after the original number of field_infos |
1340 | // so this is a position where we can add (append) new field_infos |
1341 | const u2 number_of_new_fields = add_field_infos(writer, utf8_indexes, untypedEventHandler); |
1342 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1342, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1343 | const jlong new_method_len_offset = writer.current_offset(); |
1344 | // Additional field_infos added, update classfile fields_count |
1345 | writer.write_at_offset<u2>(orig_fields_len + number_of_new_fields, new_fields_len_offset); |
1346 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1346, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1347 | // Our current location is now at classfile methods_count |
1348 | const u2 orig_methods_len = position_stream_after_methods(writer, |
1349 | orig_stream, |
1350 | utf8_indexes, |
1351 | register_klass, |
1352 | clinit_method, |
1353 | orig_method_len_offset); |
1354 | const u4 orig_attributes_count_offset = orig_stream->current_offset(); |
1355 | // Copy existing methods |
1356 | writer.write_bytes(orig_stream->buffer() + orig_method_len_offset, orig_attributes_count_offset - orig_method_len_offset); |
1357 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1357, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1358 | // We are sitting just after the original number of method_infos |
1359 | // so this is a position where we can add (append) new method_infos |
1360 | u2 number_of_new_methods = add_method_infos(writer, utf8_indexes); |
1361 | |
1362 | // We have just added the new methods. |
1363 | // |
1364 | // What about the state of <clinit>? |
1365 | // We would need to do: |
1366 | // 1. Nothing (@Registered(false) annotation) |
1367 | // 2. Build up a new <clinit> - and if the original class already contains a <clinit>, |
1368 | // merging will be neccessary. |
1369 | // |
1370 | if (register_klass) { |
1371 | insert_clinit_method(ik, parser, writer, orig_cp_len, utf8_indexes, flr_register_method_ref_index, clinit_method, THREAD__the_thread__); |
1372 | } |
1373 | number_of_new_methods += clinit_method != NULL__null ? 0 : register_klass ? 1 : 0; |
1374 | // Update classfile methods_count |
1375 | writer.write_at_offset<u2>(orig_methods_len + number_of_new_methods, new_method_len_offset); |
1376 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1376, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1377 | // Copy last remaining bytes |
1378 | writer.write_bytes(orig_stream->buffer() + orig_attributes_count_offset, orig_stream_size - orig_attributes_count_offset); |
1379 | assert(writer.is_valid(), "invariant")do { if (!(writer.is_valid())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1379, "assert(" "writer.is_valid()" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1380 | assert(writer.current_offset() > orig_stream->length(), "invariant")do { if (!(writer.current_offset() > orig_stream->length ())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1380, "assert(" "writer.current_offset() > orig_stream->length()" ") failed", "invariant"); ::breakpoint(); } } while (0); |
1381 | size_of_new_bytes = (jint)writer.current_offset(); |
1382 | return new_buffer; |
1383 | } |
1384 | |
1385 | static void log_pending_exception(oop throwable) { |
1386 | assert(throwable != NULL, "invariant")do { if (!(throwable != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1386, "assert(" "throwable != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1387 | oop msg = java_lang_Throwable::message(throwable); |
1388 | if (msg != NULL__null) { |
1389 | char* text = java_lang_String::as_utf8_string(msg); |
1390 | if (text != NULL__null) { |
1391 | log_error(jfr, system)(!(LogImpl<(LogTag::_jfr), (LogTag::_system), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_jfr), (LogTag::_system), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error> ("%s", text); |
1392 | } |
1393 | } |
1394 | } |
1395 | |
1396 | static bool should_force_instrumentation() { |
1397 | return !JfrOptionSet::allow_event_retransforms() || JfrEventClassTransformer::is_force_instrumentation(); |
1398 | } |
1399 | |
1400 | static ClassFileStream* create_new_bytes_for_subklass(const InstanceKlass* ik, const ClassFileParser& parser, JavaThread* t) { |
1401 | assert(JdkJfrEvent::is_a(ik), "invariant")do { if (!(JdkJfrEvent::is_a(ik))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1401, "assert(" "JdkJfrEvent::is_a(ik)" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1402 | DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(t))JfrJavaSupport::check_java_thread_in_vm(t); |
1403 | jint size_of_new_bytes = 0; |
1404 | const u1* new_bytes = new_bytes_for_lazy_instrumentation(ik, parser, size_of_new_bytes, t); |
1405 | if (new_bytes == NULL__null) { |
1406 | return NULL__null; |
1407 | } |
1408 | assert(new_bytes != NULL, "invariant")do { if (!(new_bytes != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1408, "assert(" "new_bytes != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1409 | assert(size_of_new_bytes > 0, "invariant")do { if (!(size_of_new_bytes > 0)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1409, "assert(" "size_of_new_bytes > 0" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1410 | |
1411 | bool force_instrumentation = should_force_instrumentation(); |
1412 | if (Jfr::is_recording() || force_instrumentation) { |
1413 | jint size_instrumented_data = 0; |
1414 | unsigned char* instrumented_data = NULL__null; |
1415 | const jclass super = (jclass)JNIHandles::make_local(ik->super()->java_mirror()); |
1416 | JfrUpcalls::new_bytes_eager_instrumentation(JfrTraceId::load_raw(ik), |
1417 | force_instrumentation, |
1418 | super, |
1419 | size_of_new_bytes, |
1420 | new_bytes, |
1421 | &size_instrumented_data, |
1422 | &instrumented_data, |
1423 | t); |
1424 | if (t->has_pending_exception()) { |
1425 | log_pending_exception(t->pending_exception()); |
1426 | t->clear_pending_exception(); |
1427 | return NULL__null; |
1428 | } |
1429 | assert(instrumented_data != NULL, "invariant")do { if (!(instrumented_data != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1429, "assert(" "instrumented_data != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1430 | assert(size_instrumented_data > 0, "invariant")do { if (!(size_instrumented_data > 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1430, "assert(" "size_instrumented_data > 0" ") failed", "invariant"); ::breakpoint(); } } while (0); |
1431 | return new ClassFileStream(instrumented_data, size_instrumented_data, NULL__null, ClassFileStream::verify); |
1432 | } |
1433 | return new ClassFileStream(new_bytes, size_of_new_bytes, NULL__null, ClassFileStream::verify); |
1434 | } |
1435 | |
1436 | static bool cache_bytes(InstanceKlass* ik, ClassFileStream* new_stream, InstanceKlass* new_ik, TRAPSJavaThread* __the_thread__) { |
1437 | assert(ik != NULL, "invariant")do { if (!(ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1437, "assert(" "ik != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1438 | assert(new_ik != NULL, "invariant")do { if (!(new_ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1438, "assert(" "new_ik != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
1439 | assert(new_ik->name() != NULL, "invariant")do { if (!(new_ik->name() != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1439, "assert(" "new_ik->name() != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1440 | assert(new_stream != NULL, "invariant")do { if (!(new_stream != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1440, "assert(" "new_stream != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1441 | assert(!HAS_PENDING_EXCEPTION, "invariant")do { if (!(!(((ThreadShadow*)__the_thread__)->has_pending_exception ()))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1441, "assert(" "!(((ThreadShadow*)__the_thread__)->has_pending_exception())" ") failed", "invariant"); ::breakpoint(); } } while (0); |
1442 | static const bool can_retransform = JfrOptionSet::allow_retransforms(); |
1443 | if (!can_retransform) { |
1444 | return true; |
1445 | } |
1446 | const jint stream_len = new_stream->length(); |
1447 | JvmtiCachedClassFileData* p = |
1448 | (JvmtiCachedClassFileData*)NEW_C_HEAP_ARRAY_RETURN_NULL(u1, offset_of(JvmtiCachedClassFileData, data) + stream_len, mtInternal)(u1*) (AllocateHeap((((size_t)((intx)&(((JvmtiCachedClassFileData *)16)->data) - 16) + stream_len)) * sizeof(u1), mtInternal , AllocFailStrategy::RETURN_NULL)); |
1449 | if (p == NULL__null) { |
1450 | log_error(jfr, system)(!(LogImpl<(LogTag::_jfr), (LogTag::_system), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_jfr), (LogTag::_system), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("Allocation using C_HEAP_ARRAY for " SIZE_FORMAT"%" "l" "u" |
1451 | " bytes failed in JfrClassAdapter::on_klass_creation", (size_t)offset_of(JvmtiCachedClassFileData, data)(size_t)((intx)&(((JvmtiCachedClassFileData*)16)->data ) - 16) + stream_len); |
1452 | return false; |
1453 | } |
1454 | p->length = stream_len; |
1455 | memcpy(p->data, new_stream->buffer(), stream_len); |
1456 | new_ik->set_cached_class_file(p); |
1457 | JvmtiCachedClassFileData* const cached_class_data = ik->get_cached_class_file(); |
1458 | if (cached_class_data != NULL__null) { |
1459 | os::free(cached_class_data); |
1460 | ik->set_cached_class_file(NULL__null); |
1461 | } |
1462 | return true; |
1463 | } |
1464 | |
1465 | static InstanceKlass* create_new_instance_klass(InstanceKlass* ik, ClassFileStream* stream, TRAPSJavaThread* __the_thread__) { |
1466 | assert(stream != NULL, "invariant")do { if (!(stream != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1466, "assert(" "stream != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
1467 | ResourceMark rm(THREAD__the_thread__); |
1468 | ClassLoaderData* const cld = ik->class_loader_data(); |
1469 | Handle pd(THREAD__the_thread__, ik->protection_domain()); |
1470 | Symbol* const class_name = ik->name(); |
1471 | const char* const klass_name = class_name != NULL__null ? class_name->as_C_string() : ""; |
Value stored to 'klass_name' during its initialization is never read | |
1472 | ClassLoadInfo cl_info(pd); |
1473 | ClassFileParser new_parser(stream, |
1474 | class_name, |
1475 | cld, |
1476 | &cl_info, |
1477 | ClassFileParser::INTERNAL, // internal visibility |
1478 | THREAD__the_thread__); |
1479 | if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) { |
1480 | log_pending_exception(PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->pending_exception())); |
1481 | CLEAR_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_exception( )); |
1482 | return NULL__null; |
1483 | } |
1484 | const ClassInstanceInfo* cl_inst_info = cl_info.class_hidden_info_ptr(); |
1485 | InstanceKlass* const new_ik = new_parser.create_instance_klass(false, *cl_inst_info, THREAD__the_thread__); |
1486 | if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) { |
1487 | log_pending_exception(PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->pending_exception())); |
1488 | CLEAR_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_exception( )); |
1489 | return NULL__null; |
1490 | } |
1491 | assert(new_ik != NULL, "invariant")do { if (!(new_ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1491, "assert(" "new_ik != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
1492 | assert(new_ik->name() != NULL, "invariant")do { if (!(new_ik->name() != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1492, "assert(" "new_ik->name() != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1493 | assert(strncmp(ik->name()->as_C_string(), new_ik->name()->as_C_string(), strlen(ik->name()->as_C_string())) == 0, "invariant")do { if (!(strncmp(ik->name()->as_C_string(), new_ik-> name()->as_C_string(), strlen(ik->name()->as_C_string ())) == 0)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1493, "assert(" "strncmp(ik->name()->as_C_string(), new_ik->name()->as_C_string(), strlen(ik->name()->as_C_string())) == 0" ") failed", "invariant"); ::breakpoint(); } } while (0); |
1494 | return cache_bytes(ik, stream, new_ik, THREAD__the_thread__) ? new_ik : NULL__null; |
1495 | } |
1496 | |
1497 | static void rewrite_klass_pointer(InstanceKlass*& ik, InstanceKlass* new_ik, ClassFileParser& parser, TRAPSJavaThread* __the_thread__) { |
1498 | assert(ik != NULL, "invariant")do { if (!(ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1498, "assert(" "ik != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1499 | assert(new_ik != NULL, "invariant")do { if (!(new_ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1499, "assert(" "new_ik != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
1500 | assert(new_ik->name() != NULL, "invariant")do { if (!(new_ik->name() != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1500, "assert(" "new_ik->name() != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1501 | assert(JdkJfrEvent::is(new_ik) || JdkJfrEvent::is_subklass(new_ik), "invariant")do { if (!(JdkJfrEvent::is(new_ik) || JdkJfrEvent::is_subklass (new_ik))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1501, "assert(" "JdkJfrEvent::is(new_ik) || JdkJfrEvent::is_subklass(new_ik)" ") failed", "invariant"); ::breakpoint(); } } while (0); |
1502 | assert(!HAS_PENDING_EXCEPTION, "invariant")do { if (!(!(((ThreadShadow*)__the_thread__)->has_pending_exception ()))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1502, "assert(" "!(((ThreadShadow*)__the_thread__)->has_pending_exception())" ") failed", "invariant"); ::breakpoint(); } } while (0); |
1503 | // assign original InstanceKlass* back onto "its" parser object for proper destruction |
1504 | parser.set_klass_to_deallocate(ik); |
1505 | // now rewrite original pointer to newly created InstanceKlass |
1506 | ik = new_ik; |
1507 | } |
1508 | |
1509 | static bool is_retransforming(const InstanceKlass* ik, TRAPSJavaThread* __the_thread__) { |
1510 | assert(ik != NULL, "invariant")do { if (!(ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1510, "assert(" "ik != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1511 | assert(JdkJfrEvent::is_a(ik), "invariant")do { if (!(JdkJfrEvent::is_a(ik))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1511, "assert(" "JdkJfrEvent::is_a(ik)" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1512 | Symbol* const name = ik->name(); |
1513 | assert(name != NULL, "invariant")do { if (!(name != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1513, "assert(" "name != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1514 | Handle class_loader(THREAD__the_thread__, ik->class_loader()); |
1515 | Handle protection_domain(THREAD__the_thread__, ik->protection_domain()); |
1516 | return SystemDictionary::find_instance_klass(name, class_loader, protection_domain) != NULL__null; |
1517 | } |
1518 | |
1519 | // target for JFR_ON_KLASS_CREATION hook |
1520 | void JfrEventClassTransformer::on_klass_creation(InstanceKlass*& ik, ClassFileParser& parser, TRAPSJavaThread* __the_thread__) { |
1521 | assert(ik != NULL, "invariant")do { if (!(ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1521, "assert(" "ik != __null" ") failed", "invariant"); :: breakpoint(); } } while (0); |
1522 | if (JdkJfrEvent::is(ik)) { |
1523 | ResourceMark rm(THREAD__the_thread__); |
1524 | HandleMark hm(THREAD__the_thread__); |
1525 | ClassFileStream* new_stream = create_new_bytes_for_event_klass(ik, parser, THREAD__the_thread__); |
1526 | if (new_stream == NULL__null) { |
1527 | log_error(jfr, system)(!(LogImpl<(LogTag::_jfr), (LogTag::_system), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_jfr), (LogTag::_system), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("JfrClassAdapter: unable to create ClassFileStream"); |
1528 | return; |
1529 | } |
1530 | assert(new_stream != NULL, "invariant")do { if (!(new_stream != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1530, "assert(" "new_stream != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1531 | InstanceKlass* new_ik = create_new_instance_klass(ik, new_stream, THREAD__the_thread__); |
1532 | if (new_ik == NULL__null) { |
1533 | log_error(jfr, system)(!(LogImpl<(LogTag::_jfr), (LogTag::_system), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_jfr), (LogTag::_system), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("JfrClassAdapter: unable to create InstanceKlass"); |
1534 | return; |
1535 | } |
1536 | assert(new_ik != NULL, "invariant")do { if (!(new_ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1536, "assert(" "new_ik != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
1537 | // We now need to explicitly tag the replaced klass as the jdk.jfr.Event klass |
1538 | assert(!JdkJfrEvent::is(new_ik), "invariant")do { if (!(!JdkJfrEvent::is(new_ik))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1538, "assert(" "!JdkJfrEvent::is(new_ik)" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1539 | JdkJfrEvent::tag_as(new_ik); |
1540 | assert(JdkJfrEvent::is(new_ik), "invariant")do { if (!(JdkJfrEvent::is(new_ik))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1540, "assert(" "JdkJfrEvent::is(new_ik)" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1541 | rewrite_klass_pointer(ik, new_ik, parser, THREAD__the_thread__); |
1542 | return; |
1543 | } |
1544 | assert(JdkJfrEvent::is_subklass(ik), "invariant")do { if (!(JdkJfrEvent::is_subklass(ik))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1544, "assert(" "JdkJfrEvent::is_subklass(ik)" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1545 | if (ik->is_abstract() || is_retransforming(ik, THREAD__the_thread__)) { |
1546 | // abstract and scratch classes are not instrumented |
1547 | return; |
1548 | } |
1549 | ResourceMark rm(THREAD__the_thread__); |
1550 | HandleMark hm(THREAD__the_thread__); |
1551 | ClassFileStream* const new_stream = create_new_bytes_for_subklass(ik, parser, THREAD__the_thread__); |
1552 | if (NULL__null == new_stream) { |
1553 | log_error(jfr, system)(!(LogImpl<(LogTag::_jfr), (LogTag::_system), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_jfr), (LogTag::_system), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("JfrClassAdapter: unable to create ClassFileStream"); |
1554 | return; |
1555 | } |
1556 | assert(new_stream != NULL, "invariant")do { if (!(new_stream != __null)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1556, "assert(" "new_stream != __null" ") failed", "invariant" ); ::breakpoint(); } } while (0); |
1557 | InstanceKlass* new_ik = create_new_instance_klass(ik, new_stream, THREAD__the_thread__); |
1558 | if (new_ik == NULL__null) { |
1559 | log_error(jfr, system)(!(LogImpl<(LogTag::_jfr), (LogTag::_system), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::is_level(LogLevel::Error))) ? (void)0 : LogImpl<(LogTag ::_jfr), (LogTag::_system), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel ::Error>("JfrClassAdapter: unable to create InstanceKlass"); |
1560 | return; |
1561 | } |
1562 | assert(new_ik != NULL, "invariant")do { if (!(new_ik != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1562, "assert(" "new_ik != __null" ") failed", "invariant") ; ::breakpoint(); } } while (0); |
1563 | // would have been tagged already as a subklass during the normal process of traceid assignment |
1564 | assert(JdkJfrEvent::is_subklass(new_ik), "invariant")do { if (!(JdkJfrEvent::is_subklass(new_ik))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp" , 1564, "assert(" "JdkJfrEvent::is_subklass(new_ik)" ") failed" , "invariant"); ::breakpoint(); } } while (0); |
1565 | traceid id = ik->trace_id(); |
1566 | ik->set_trace_id(0); |
1567 | new_ik->set_trace_id(id); |
1568 | rewrite_klass_pointer(ik, new_ik, parser, THREAD__the_thread__); |
1569 | } |
1570 | |
1571 | static bool _force_instrumentation = false; |
1572 | void JfrEventClassTransformer::set_force_instrumentation(bool force_instrumentation) { |
1573 | _force_instrumentation = force_instrumentation; |
1574 | } |
1575 | |
1576 | bool JfrEventClassTransformer::is_force_instrumentation() { |
1577 | return _force_instrumentation; |
1578 | } |