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