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