Mercurial > hg > truffle
annotate src/share/vm/prims/jvmtiClassFileReconstituter.cpp @ 1716:be3f9c242c9d
6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
Summary: GC workers now recognize an intermediate transient state of blocks which are allocated but have not yet completed initialization. blk_start() calls do not attempt to determine the size of a block in the transient state, rather waiting for the block to become initialized so that it is safe to query its size. Audited and ensured the order of initialization of object fields (klass, free bit and size) to respect block state transition protocol. Also included some new assertion checking code enabled in debug mode.
Reviewed-by: chrisphi, johnc, poonam
author | ysr |
---|---|
date | Mon, 16 Aug 2010 15:58:42 -0700 |
parents | e9ff18c4ace7 |
children | f95d63e2154a |
rev | line source |
---|---|
0 | 1 /* |
1579 | 2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 # include "incls/_precompiled.incl" | |
25 # include "incls/_jvmtiClassFileReconstituter.cpp.incl" | |
26 | |
27 // FIXME: add Deprecated, LVT, LVTT attributes | |
28 // FIXME: fix Synthetic attribute | |
29 // FIXME: per Serguei, add error return handling for constantPoolOopDesc::copy_cpool_bytes() | |
30 | |
31 | |
32 // Write the field information portion of ClassFile structure | |
33 // JVMSpec| u2 fields_count; | |
34 // JVMSpec| field_info fields[fields_count]; | |
35 void JvmtiClassFileReconstituter::write_field_infos() { | |
36 HandleMark hm(thread()); | |
37 typeArrayHandle fields(thread(), ikh()->fields()); | |
38 int fields_length = fields->length(); | |
39 int num_fields = fields_length / instanceKlass::next_offset; | |
40 objArrayHandle fields_anno(thread(), ikh()->fields_annotations()); | |
41 | |
42 write_u2(num_fields); | |
43 for (int index = 0; index < fields_length; index += instanceKlass::next_offset) { | |
44 AccessFlags access_flags; | |
45 int flags = fields->ushort_at(index + instanceKlass::access_flags_offset); | |
46 access_flags.set_flags(flags); | |
47 int name_index = fields->ushort_at(index + instanceKlass::name_index_offset); | |
48 int signature_index = fields->ushort_at(index + instanceKlass::signature_index_offset); | |
49 int initial_value_index = fields->ushort_at(index + instanceKlass::initval_index_offset); | |
50 guarantee(name_index != 0 && signature_index != 0, "bad constant pool index for field"); | |
51 int offset = ikh()->offset_from_fields( index ); | |
52 int generic_signature_index = | |
53 fields->ushort_at(index + instanceKlass::generic_signature_offset); | |
54 typeArrayHandle anno(thread(), fields_anno.not_null() ? | |
55 (typeArrayOop)(fields_anno->obj_at(index / instanceKlass::next_offset)) : | |
56 (typeArrayOop)NULL); | |
57 | |
58 // JVMSpec| field_info { | |
59 // JVMSpec| u2 access_flags; | |
60 // JVMSpec| u2 name_index; | |
61 // JVMSpec| u2 descriptor_index; | |
62 // JVMSpec| u2 attributes_count; | |
63 // JVMSpec| attribute_info attributes[attributes_count]; | |
64 // JVMSpec| } | |
65 | |
66 write_u2(flags & JVM_RECOGNIZED_FIELD_MODIFIERS); | |
67 write_u2(name_index); | |
68 write_u2(signature_index); | |
69 int attr_count = 0; | |
70 if (initial_value_index != 0) { | |
71 ++attr_count; | |
72 } | |
73 if (access_flags.is_synthetic()) { | |
74 // ++attr_count; | |
75 } | |
76 if (generic_signature_index != 0) { | |
77 ++attr_count; | |
78 } | |
79 if (anno.not_null()) { | |
80 ++attr_count; // has RuntimeVisibleAnnotations attribute | |
81 } | |
82 | |
83 write_u2(attr_count); | |
84 | |
85 if (initial_value_index != 0) { | |
86 write_attribute_name_index("ConstantValue"); | |
87 write_u4(2); //length always 2 | |
88 write_u2(initial_value_index); | |
89 } | |
90 if (access_flags.is_synthetic()) { | |
91 // write_synthetic_attribute(); | |
92 } | |
93 if (generic_signature_index != 0) { | |
94 write_signature_attribute(generic_signature_index); | |
95 } | |
96 if (anno.not_null()) { | |
97 write_annotations_attribute("RuntimeVisibleAnnotations", anno); | |
98 } | |
99 } | |
100 } | |
101 | |
102 // Write Code attribute | |
103 // JVMSpec| Code_attribute { | |
104 // JVMSpec| u2 attribute_name_index; | |
105 // JVMSpec| u4 attribute_length; | |
106 // JVMSpec| u2 max_stack; | |
107 // JVMSpec| u2 max_locals; | |
108 // JVMSpec| u4 code_length; | |
109 // JVMSpec| u1 code[code_length]; | |
110 // JVMSpec| u2 exception_table_length; | |
111 // JVMSpec| { u2 start_pc; | |
112 // JVMSpec| u2 end_pc; | |
113 // JVMSpec| u2 handler_pc; | |
114 // JVMSpec| u2 catch_type; | |
115 // JVMSpec| } exception_table[exception_table_length]; | |
116 // JVMSpec| u2 attributes_count; | |
117 // JVMSpec| attribute_info attributes[attributes_count]; | |
118 // JVMSpec| } | |
119 void JvmtiClassFileReconstituter::write_code_attribute(methodHandle method) { | |
120 constMethodHandle const_method(thread(), method->constMethod()); | |
121 u2 line_num_cnt = 0; | |
122 int stackmap_len = 0; | |
123 | |
124 // compute number and length of attributes -- FIXME: for now no LVT | |
125 int attr_count = 0; | |
126 int attr_size = 0; | |
127 if (const_method->has_linenumber_table()) { | |
128 line_num_cnt = line_number_table_entries(method); | |
129 if (line_num_cnt != 0) { | |
130 ++attr_count; | |
131 // Compute the complete size of the line number table attribute: | |
132 // LineNumberTable_attribute { | |
133 // u2 attribute_name_index; | |
134 // u4 attribute_length; | |
135 // u2 line_number_table_length; | |
136 // { u2 start_pc; | |
137 // u2 line_number; | |
138 // } line_number_table[line_number_table_length]; | |
139 // } | |
140 attr_size += 2 + 4 + 2 + line_num_cnt * (2 + 2); | |
141 } | |
142 } | |
143 if (method->has_stackmap_table()) { | |
144 stackmap_len = method->stackmap_data()->length(); | |
145 if (stackmap_len != 0) { | |
146 ++attr_count; | |
147 // Compute the size of the stack map table attribute (VM stores raw): | |
148 // StackMapTable_attribute { | |
149 // u2 attribute_name_index; | |
150 // u4 attribute_length; | |
151 // u2 number_of_entries; | |
152 // stack_map_frame_entries[number_of_entries]; | |
153 // } | |
154 attr_size += 2 + 4 + stackmap_len; | |
155 } | |
156 } | |
157 | |
158 typeArrayHandle exception_table(thread(), const_method->exception_table()); | |
159 int exception_table_length = exception_table->length(); | |
160 int exception_table_entries = exception_table_length / 4; | |
161 int code_size = const_method->code_size(); | |
162 int size = | |
163 2+2+4 + // max_stack, max_locals, code_length | |
164 code_size + // code | |
165 2 + // exception_table_length | |
166 (2+2+2+2) * exception_table_entries + // exception_table | |
167 2 + // attributes_count | |
168 attr_size; // attributes | |
169 | |
170 write_attribute_name_index("Code"); | |
171 write_u4(size); | |
172 write_u2(method->max_stack()); | |
173 write_u2(method->max_locals()); | |
174 write_u4(code_size); | |
175 copy_bytecodes(method, (unsigned char*)writeable_address(code_size)); | |
176 write_u2(exception_table_entries); | |
177 for (int index = 0; index < exception_table_length; ) { | |
178 write_u2(exception_table->int_at(index++)); | |
179 write_u2(exception_table->int_at(index++)); | |
180 write_u2(exception_table->int_at(index++)); | |
181 write_u2(exception_table->int_at(index++)); | |
182 } | |
183 write_u2(attr_count); | |
184 if (line_num_cnt != 0) { | |
185 write_line_number_table_attribute(method, line_num_cnt); | |
186 } | |
187 if (stackmap_len != 0) { | |
188 write_stackmap_table_attribute(method, stackmap_len); | |
189 } | |
190 | |
191 // FIXME: write LVT attribute | |
192 } | |
193 | |
194 // Write Exceptions attribute | |
195 // JVMSpec| Exceptions_attribute { | |
196 // JVMSpec| u2 attribute_name_index; | |
197 // JVMSpec| u4 attribute_length; | |
198 // JVMSpec| u2 number_of_exceptions; | |
199 // JVMSpec| u2 exception_index_table[number_of_exceptions]; | |
200 // JVMSpec| } | |
201 void JvmtiClassFileReconstituter::write_exceptions_attribute(constMethodHandle const_method) { | |
202 CheckedExceptionElement* checked_exceptions = const_method->checked_exceptions_start(); | |
203 int checked_exceptions_length = const_method->checked_exceptions_length(); | |
204 int size = | |
205 2 + // number_of_exceptions | |
206 2 * checked_exceptions_length; // exception_index_table | |
207 | |
208 write_attribute_name_index("Exceptions"); | |
209 write_u4(size); | |
210 write_u2(checked_exceptions_length); | |
211 for (int index = 0; index < checked_exceptions_length; index++) { | |
212 write_u2(checked_exceptions[index].class_cp_index); | |
213 } | |
214 } | |
215 | |
216 // Write SourceFile attribute | |
217 // JVMSpec| SourceFile_attribute { | |
218 // JVMSpec| u2 attribute_name_index; | |
219 // JVMSpec| u4 attribute_length; | |
220 // JVMSpec| u2 sourcefile_index; | |
221 // JVMSpec| } | |
222 void JvmtiClassFileReconstituter::write_source_file_attribute() { | |
223 assert(ikh()->source_file_name() != NULL, "caller must check"); | |
224 | |
225 write_attribute_name_index("SourceFile"); | |
226 write_u4(2); // always length 2 | |
227 write_u2(symbol_to_cpool_index(ikh()->source_file_name())); | |
228 } | |
229 | |
230 // Write SourceDebugExtension attribute | |
231 // JSR45| SourceDebugExtension_attribute { | |
232 // JSR45| u2 attribute_name_index; | |
233 // JSR45| u4 attribute_length; | |
234 // JSR45| u2 sourcefile_index; | |
235 // JSR45| } | |
236 void JvmtiClassFileReconstituter::write_source_debug_extension_attribute() { | |
237 assert(ikh()->source_debug_extension() != NULL, "caller must check"); | |
238 | |
239 write_attribute_name_index("SourceDebugExtension"); | |
240 write_u4(2); // always length 2 | |
241 write_u2(symbol_to_cpool_index(ikh()->source_debug_extension())); | |
242 } | |
243 | |
244 // Write (generic) Signature attribute | |
245 // JVMSpec| Signature_attribute { | |
246 // JVMSpec| u2 attribute_name_index; | |
247 // JVMSpec| u4 attribute_length; | |
248 // JVMSpec| u2 signature_index; | |
249 // JVMSpec| } | |
250 void JvmtiClassFileReconstituter::write_signature_attribute(u2 generic_signature_index) { | |
251 write_attribute_name_index("Signature"); | |
252 write_u4(2); // always length 2 | |
253 write_u2(generic_signature_index); | |
254 } | |
255 | |
256 // Compute the number of entries in the InnerClasses attribute | |
257 u2 JvmtiClassFileReconstituter::inner_classes_attribute_length() { | |
258 typeArrayOop inner_class_list = ikh()->inner_classes(); | |
259 return (inner_class_list == NULL) ? 0 : inner_class_list->length(); | |
260 } | |
261 | |
262 // Write an annotation attribute. The VM stores them in raw form, so all we need | |
263 // to do is add the attrubute name and fill in the length. | |
264 // JSR202| *Annotations_attribute { | |
265 // JSR202| u2 attribute_name_index; | |
266 // JSR202| u4 attribute_length; | |
267 // JSR202| ... | |
268 // JSR202| } | |
269 void JvmtiClassFileReconstituter::write_annotations_attribute(const char* attr_name, | |
270 typeArrayHandle annos) { | |
271 u4 length = annos->length(); | |
272 write_attribute_name_index(attr_name); | |
273 write_u4(length); | |
274 memcpy(writeable_address(length), annos->byte_at_addr(0), length); | |
275 } | |
276 | |
277 | |
278 // Write InnerClasses attribute | |
279 // JVMSpec| InnerClasses_attribute { | |
280 // JVMSpec| u2 attribute_name_index; | |
281 // JVMSpec| u4 attribute_length; | |
282 // JVMSpec| u2 number_of_classes; | |
283 // JVMSpec| { u2 inner_class_info_index; | |
284 // JVMSpec| u2 outer_class_info_index; | |
285 // JVMSpec| u2 inner_name_index; | |
286 // JVMSpec| u2 inner_class_access_flags; | |
287 // JVMSpec| } classes[number_of_classes]; | |
288 // JVMSpec| } | |
289 void JvmtiClassFileReconstituter::write_inner_classes_attribute(int length) { | |
290 typeArrayOop inner_class_list = ikh()->inner_classes(); | |
291 guarantee(inner_class_list != NULL && inner_class_list->length() == length, | |
292 "caller must check"); | |
293 typeArrayHandle inner_class_list_h(thread(), inner_class_list); | |
294 assert (length % instanceKlass::inner_class_next_offset == 0, "just checking"); | |
295 u2 entry_count = length / instanceKlass::inner_class_next_offset; | |
296 u4 size = 2 + entry_count * (2+2+2+2); | |
297 | |
298 write_attribute_name_index("InnerClasses"); | |
299 write_u4(size); | |
300 write_u2(entry_count); | |
301 for (int i = 0; i < length; i += instanceKlass::inner_class_next_offset) { | |
302 write_u2(inner_class_list_h->ushort_at( | |
303 i + instanceKlass::inner_class_inner_class_info_offset)); | |
304 write_u2(inner_class_list_h->ushort_at( | |
305 i + instanceKlass::inner_class_outer_class_info_offset)); | |
306 write_u2(inner_class_list_h->ushort_at( | |
307 i + instanceKlass::inner_class_inner_name_offset)); | |
308 write_u2(inner_class_list_h->ushort_at( | |
309 i + instanceKlass::inner_class_access_flags_offset)); | |
310 } | |
311 } | |
312 | |
313 // Write Synthetic attribute | |
314 // JVMSpec| Synthetic_attribute { | |
315 // JVMSpec| u2 attribute_name_index; | |
316 // JVMSpec| u4 attribute_length; | |
317 // JVMSpec| } | |
318 void JvmtiClassFileReconstituter::write_synthetic_attribute() { | |
319 write_attribute_name_index("Synthetic"); | |
320 write_u4(0); //length always zero | |
321 } | |
322 | |
323 // Compute size of LineNumberTable | |
324 u2 JvmtiClassFileReconstituter::line_number_table_entries(methodHandle method) { | |
325 // The line number table is compressed so we don't know how big it is until decompressed. | |
326 // Decompression is really fast so we just do it twice. | |
327 u2 num_entries = 0; | |
328 CompressedLineNumberReadStream stream(method->compressed_linenumber_table()); | |
329 while (stream.read_pair()) { | |
330 num_entries++; | |
331 } | |
332 return num_entries; | |
333 } | |
334 | |
335 // Write LineNumberTable attribute | |
336 // JVMSpec| LineNumberTable_attribute { | |
337 // JVMSpec| u2 attribute_name_index; | |
338 // JVMSpec| u4 attribute_length; | |
339 // JVMSpec| u2 line_number_table_length; | |
340 // JVMSpec| { u2 start_pc; | |
341 // JVMSpec| u2 line_number; | |
342 // JVMSpec| } line_number_table[line_number_table_length]; | |
343 // JVMSpec| } | |
344 void JvmtiClassFileReconstituter::write_line_number_table_attribute(methodHandle method, | |
345 u2 num_entries) { | |
346 | |
347 write_attribute_name_index("LineNumberTable"); | |
348 write_u4(2 + num_entries * (2 + 2)); | |
349 write_u2(num_entries); | |
350 | |
351 CompressedLineNumberReadStream stream(method->compressed_linenumber_table()); | |
352 while (stream.read_pair()) { | |
353 write_u2(stream.bci()); | |
354 write_u2(stream.line()); | |
355 } | |
356 } | |
357 | |
358 // Write stack map table attribute | |
359 // JSR-202| StackMapTable_attribute { | |
360 // JSR-202| u2 attribute_name_index; | |
361 // JSR-202| u4 attribute_length; | |
362 // JSR-202| u2 number_of_entries; | |
363 // JSR-202| stack_map_frame_entries[number_of_entries]; | |
364 // JSR-202| } | |
365 void JvmtiClassFileReconstituter::write_stackmap_table_attribute(methodHandle method, | |
366 int stackmap_len) { | |
367 | |
368 write_attribute_name_index("StackMapTable"); | |
369 write_u4(stackmap_len); | |
370 memcpy( | |
371 writeable_address(stackmap_len), | |
372 (void*)(method->stackmap_data()->byte_at_addr(0)), | |
373 stackmap_len); | |
374 } | |
375 | |
376 // Write one method_info structure | |
377 // JVMSpec| method_info { | |
378 // JVMSpec| u2 access_flags; | |
379 // JVMSpec| u2 name_index; | |
380 // JVMSpec| u2 descriptor_index; | |
381 // JVMSpec| u2 attributes_count; | |
382 // JVMSpec| attribute_info attributes[attributes_count]; | |
383 // JVMSpec| } | |
384 void JvmtiClassFileReconstituter::write_method_info(methodHandle method) { | |
385 AccessFlags access_flags = method->access_flags(); | |
386 constMethodHandle const_method(thread(), method->constMethod()); | |
387 u2 generic_signature_index = const_method->generic_signature_index(); | |
388 typeArrayHandle anno(thread(), method->annotations()); | |
389 typeArrayHandle param_anno(thread(), method->parameter_annotations()); | |
390 typeArrayHandle default_anno(thread(), method->annotation_default()); | |
391 | |
392 write_u2(access_flags.get_flags() & JVM_RECOGNIZED_METHOD_MODIFIERS); | |
393 write_u2(const_method->name_index()); | |
394 write_u2(const_method->signature_index()); | |
395 | |
396 // write attributes in the same order javac does, so we can test with byte for | |
397 // byte comparison | |
398 int attr_count = 0; | |
399 if (const_method->code_size() != 0) { | |
400 ++attr_count; // has Code attribute | |
401 } | |
402 if (const_method->has_checked_exceptions()) { | |
403 ++attr_count; // has Exceptions attribute | |
404 } | |
405 if (default_anno.not_null()) { | |
406 ++attr_count; // has AnnotationDefault attribute | |
407 } | |
408 // Deprecated attribute would go here | |
409 if (access_flags.is_synthetic()) { // FIXME | |
410 // ++attr_count; | |
411 } | |
412 if (generic_signature_index != 0) { | |
413 ++attr_count; | |
414 } | |
415 if (anno.not_null()) { | |
416 ++attr_count; // has RuntimeVisibleAnnotations attribute | |
417 } | |
418 if (param_anno.not_null()) { | |
419 ++attr_count; // has RuntimeVisibleParameterAnnotations attribute | |
420 } | |
421 | |
422 write_u2(attr_count); | |
423 if (const_method->code_size() > 0) { | |
424 write_code_attribute(method); | |
425 } | |
426 if (const_method->has_checked_exceptions()) { | |
427 write_exceptions_attribute(const_method); | |
428 } | |
429 if (default_anno.not_null()) { | |
430 write_annotations_attribute("AnnotationDefault", default_anno); | |
431 } | |
432 // Deprecated attribute would go here | |
433 if (access_flags.is_synthetic()) { | |
434 // write_synthetic_attribute(); | |
435 } | |
436 if (generic_signature_index != 0) { | |
437 write_signature_attribute(generic_signature_index); | |
438 } | |
439 if (anno.not_null()) { | |
440 write_annotations_attribute("RuntimeVisibleAnnotations", anno); | |
441 } | |
442 if (param_anno.not_null()) { | |
443 write_annotations_attribute("RuntimeVisibleParameterAnnotations", param_anno); | |
444 } | |
445 } | |
446 | |
447 // Write the class attributes portion of ClassFile structure | |
448 // JVMSpec| u2 attributes_count; | |
449 // JVMSpec| attribute_info attributes[attributes_count]; | |
450 void JvmtiClassFileReconstituter::write_class_attributes() { | |
451 u2 inner_classes_length = inner_classes_attribute_length(); | |
452 symbolHandle generic_signature(thread(), ikh()->generic_signature()); | |
453 typeArrayHandle anno(thread(), ikh()->class_annotations()); | |
454 | |
455 int attr_count = 0; | |
456 if (generic_signature() != NULL) { | |
457 ++attr_count; | |
458 } | |
459 if (ikh()->source_file_name() != NULL) { | |
460 ++attr_count; | |
461 } | |
462 if (ikh()->source_debug_extension() != NULL) { | |
463 ++attr_count; | |
464 } | |
465 if (inner_classes_length > 0) { | |
466 ++attr_count; | |
467 } | |
468 if (anno.not_null()) { | |
469 ++attr_count; // has RuntimeVisibleAnnotations attribute | |
470 } | |
471 | |
472 write_u2(attr_count); | |
473 | |
474 if (generic_signature() != NULL) { | |
475 write_signature_attribute(symbol_to_cpool_index(generic_signature())); | |
476 } | |
477 if (ikh()->source_file_name() != NULL) { | |
478 write_source_file_attribute(); | |
479 } | |
480 if (ikh()->source_debug_extension() != NULL) { | |
481 write_source_debug_extension_attribute(); | |
482 } | |
483 if (inner_classes_length > 0) { | |
484 write_inner_classes_attribute(inner_classes_length); | |
485 } | |
486 if (anno.not_null()) { | |
487 write_annotations_attribute("RuntimeVisibleAnnotations", anno); | |
488 } | |
489 } | |
490 | |
491 // Write the method information portion of ClassFile structure | |
492 // JVMSpec| u2 methods_count; | |
493 // JVMSpec| method_info methods[methods_count]; | |
494 void JvmtiClassFileReconstituter::write_method_infos() { | |
495 HandleMark hm(thread()); | |
496 objArrayHandle methods(thread(), ikh()->methods()); | |
497 int num_methods = methods->length(); | |
498 | |
499 write_u2(num_methods); | |
500 if (JvmtiExport::can_maintain_original_method_order()) { | |
501 int index; | |
502 int original_index; | |
503 int* method_order = NEW_RESOURCE_ARRAY(int, num_methods); | |
504 | |
505 // invert the method order mapping | |
506 for (index = 0; index < num_methods; index++) { | |
507 original_index = ikh()->method_ordering()->int_at(index); | |
508 assert(original_index >= 0 && original_index < num_methods, | |
509 "invalid original method index"); | |
510 method_order[original_index] = index; | |
511 } | |
512 | |
513 // write in original order | |
514 for (original_index = 0; original_index < num_methods; original_index++) { | |
515 index = method_order[original_index]; | |
516 methodHandle method(thread(), (methodOop)(ikh()->methods()->obj_at(index))); | |
517 write_method_info(method); | |
518 } | |
519 } else { | |
520 // method order not preserved just dump the method infos | |
521 for (int index = 0; index < num_methods; index++) { | |
522 methodHandle method(thread(), (methodOop)(ikh()->methods()->obj_at(index))); | |
523 write_method_info(method); | |
524 } | |
525 } | |
526 } | |
527 | |
528 void JvmtiClassFileReconstituter::write_class_file_format() { | |
529 ReallocMark(); | |
530 | |
531 // JVMSpec| ClassFile { | |
532 // JVMSpec| u4 magic; | |
533 write_u4(0xCAFEBABE); | |
534 | |
535 // JVMSpec| u2 minor_version; | |
536 // JVMSpec| u2 major_version; | |
537 write_u2(ikh()->minor_version()); | |
538 u2 major = ikh()->major_version(); | |
539 write_u2(major); | |
540 | |
541 // JVMSpec| u2 constant_pool_count; | |
542 // JVMSpec| cp_info constant_pool[constant_pool_count-1]; | |
543 write_u2(cpool()->length()); | |
544 copy_cpool_bytes(writeable_address(cpool_size())); | |
545 | |
546 // JVMSpec| u2 access_flags; | |
547 write_u2(ikh()->access_flags().get_flags() & JVM_RECOGNIZED_CLASS_MODIFIERS); | |
548 | |
549 // JVMSpec| u2 this_class; | |
550 // JVMSpec| u2 super_class; | |
551 write_u2(class_symbol_to_cpool_index(ikh()->name())); | |
552 klassOop super_class = ikh()->super(); | |
553 write_u2(super_class == NULL? 0 : // zero for java.lang.Object | |
554 class_symbol_to_cpool_index(super_class->klass_part()->name())); | |
555 | |
556 // JVMSpec| u2 interfaces_count; | |
557 // JVMSpec| u2 interfaces[interfaces_count]; | |
558 objArrayHandle interfaces(thread(), ikh()->local_interfaces()); | |
559 int num_interfaces = interfaces->length(); | |
560 write_u2(num_interfaces); | |
561 for (int index = 0; index < num_interfaces; index++) { | |
562 HandleMark hm(thread()); | |
563 instanceKlassHandle iikh(thread(), klassOop(interfaces->obj_at(index))); | |
564 write_u2(class_symbol_to_cpool_index(iikh->name())); | |
565 } | |
566 | |
567 // JVMSpec| u2 fields_count; | |
568 // JVMSpec| field_info fields[fields_count]; | |
569 write_field_infos(); | |
570 | |
571 // JVMSpec| u2 methods_count; | |
572 // JVMSpec| method_info methods[methods_count]; | |
573 write_method_infos(); | |
574 | |
575 // JVMSpec| u2 attributes_count; | |
576 // JVMSpec| attribute_info attributes[attributes_count]; | |
577 // JVMSpec| } /* end ClassFile 8? | |
578 write_class_attributes(); | |
579 } | |
580 | |
581 address JvmtiClassFileReconstituter::writeable_address(size_t size) { | |
582 size_t used_size = _buffer_ptr - _buffer; | |
583 if (size + used_size >= _buffer_size) { | |
584 // compute the new buffer size: must be at least twice as big as before | |
585 // plus whatever new is being used; then convert to nice clean block boundary | |
586 size_t new_buffer_size = (size + _buffer_size*2 + 1) / initial_buffer_size | |
587 * initial_buffer_size; | |
588 | |
589 // VM goes belly-up if the memory isn't available, so cannot do OOM processing | |
590 _buffer = REALLOC_RESOURCE_ARRAY(u1, _buffer, _buffer_size, new_buffer_size); | |
591 _buffer_size = new_buffer_size; | |
592 _buffer_ptr = _buffer + used_size; | |
593 } | |
594 u1* ret_ptr = _buffer_ptr; | |
595 _buffer_ptr += size; | |
596 return ret_ptr; | |
597 } | |
598 | |
599 void JvmtiClassFileReconstituter::write_attribute_name_index(const char* name) { | |
600 unsigned int hash_ignored; | |
601 symbolOop sym = SymbolTable::lookup_only(name, (int)strlen(name), hash_ignored); | |
602 assert(sym != NULL, "attribute name symbol not found"); | |
603 u2 attr_name_index = symbol_to_cpool_index(sym); | |
604 assert(attr_name_index != 0, "attribute name symbol not in constant pool"); | |
605 write_u2(attr_name_index); | |
606 } | |
607 | |
608 void JvmtiClassFileReconstituter::write_u1(u1 x) { | |
609 *writeable_address(1) = x; | |
610 } | |
611 | |
612 void JvmtiClassFileReconstituter::write_u2(u2 x) { | |
613 Bytes::put_Java_u2(writeable_address(2), x); | |
614 } | |
615 | |
616 void JvmtiClassFileReconstituter::write_u4(u4 x) { | |
617 Bytes::put_Java_u4(writeable_address(4), x); | |
618 } | |
619 | |
620 void JvmtiClassFileReconstituter::write_u8(u8 x) { | |
621 Bytes::put_Java_u8(writeable_address(8), x); | |
622 } | |
623 | |
624 void JvmtiClassFileReconstituter::copy_bytecodes(methodHandle mh, | |
625 unsigned char* bytecodes) { | |
626 // use a BytecodeStream to iterate over the bytecodes. JVM/fast bytecodes | |
627 // and the breakpoint bytecode are converted to their original bytecodes. | |
628 | |
629 BytecodeStream bs(mh); | |
630 | |
631 unsigned char* p = bytecodes; | |
632 Bytecodes::Code code; | |
633 bool is_rewritten = instanceKlass::cast(mh->method_holder())->is_rewritten(); | |
634 | |
635 while ((code = bs.next()) >= 0) { | |
636 assert(Bytecodes::is_java_code(code), "sanity check"); | |
637 assert(code != Bytecodes::_breakpoint, "sanity check"); | |
638 | |
639 // length of bytecode (mnemonic + operands) | |
640 address bcp = bs.bcp(); | |
1565 | 641 int len = bs.instruction_size(); |
0 | 642 assert(len > 0, "length must be > 0"); |
643 | |
644 // copy the bytecodes | |
645 *p = (unsigned char) (bs.is_wide()? Bytecodes::_wide : code); | |
646 if (len > 1) { | |
647 memcpy(p+1, bcp+1, len-1); | |
648 } | |
649 | |
650 // During linking the get/put and invoke instructions are rewritten | |
651 // with an index into the constant pool cache. The original constant | |
652 // pool index must be returned to caller. Rewrite the index. | |
653 if (is_rewritten && len >= 3) { | |
654 switch (code) { | |
655 case Bytecodes::_getstatic : // fall through | |
656 case Bytecodes::_putstatic : // fall through | |
657 case Bytecodes::_getfield : // fall through | |
658 case Bytecodes::_putfield : // fall through | |
659 case Bytecodes::_invokevirtual : // fall through | |
660 case Bytecodes::_invokespecial : // fall through | |
661 case Bytecodes::_invokestatic : // fall through | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
662 case Bytecodes::_invokedynamic : // fall through |
0 | 663 case Bytecodes::_invokeinterface : |
664 assert(len == 3 || (code == Bytecodes::_invokeinterface && len ==5), | |
665 "sanity check"); | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
666 int cpci = Bytes::get_native_u2(bcp+1); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
667 bool is_invokedynamic = (EnableInvokeDynamic && code == Bytecodes::_invokedynamic); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
668 if (is_invokedynamic) |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
669 cpci = Bytes::get_native_u4(bcp+1); |
0 | 670 // cache cannot be pre-fetched since some classes won't have it yet |
671 ConstantPoolCacheEntry* entry = | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
672 mh->constants()->cache()->main_entry_at(cpci); |
0 | 673 int i = entry->constant_pool_index(); |
674 assert(i < mh->constants()->length(), "sanity check"); | |
675 Bytes::put_Java_u2((address)(p+1), (u2)i); // java byte ordering | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
0
diff
changeset
|
676 if (is_invokedynamic) *(p+3) = *(p+4) = 0; |
0 | 677 break; |
678 } | |
679 } | |
680 | |
681 p += len; | |
682 } | |
683 } |