Mercurial > hg > truffle
comparison src/share/vm/classfile/classFileParser.cpp @ 1922:5caa30ea147b
Merge
author | iveresov |
---|---|
date | Mon, 08 Nov 2010 14:33:48 -0800 |
parents | 6412b3805cd6 3b2dea75431e |
children | f95d63e2154a |
comparison
equal
deleted
inserted
replaced
1892:4ac698856c43 | 1922:5caa30ea147b |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
71 int lengths[SymbolTable::symbol_alloc_batch_size]; | 71 int lengths[SymbolTable::symbol_alloc_batch_size]; |
72 int indices[SymbolTable::symbol_alloc_batch_size]; | 72 int indices[SymbolTable::symbol_alloc_batch_size]; |
73 unsigned int hashValues[SymbolTable::symbol_alloc_batch_size]; | 73 unsigned int hashValues[SymbolTable::symbol_alloc_batch_size]; |
74 int names_count = 0; | 74 int names_count = 0; |
75 | 75 |
76 // Side buffer for operands of variable-sized (InvokeDynamic) entries. | |
77 GrowableArray<int>* operands = NULL; | |
78 #ifdef ASSERT | |
79 GrowableArray<int>* indy_instructions = new GrowableArray<int>(THREAD, 10); | |
80 #endif | |
81 | |
76 // parsing Index 0 is unused | 82 // parsing Index 0 is unused |
77 for (int index = 1; index < length; index++) { | 83 for (int index = 1; index < length; index++) { |
78 // Each of the following case guarantees one more byte in the stream | 84 // Each of the following case guarantees one more byte in the stream |
79 // for the following tag or the access_flags following constant pool, | 85 // for the following tag or the access_flags following constant pool, |
80 // so we don't need bounds-check for reading tag. | 86 // so we don't need bounds-check for reading tag. |
139 cp->method_type_index_at_put(index, signature_index); | 145 cp->method_type_index_at_put(index, signature_index); |
140 } else { | 146 } else { |
141 ShouldNotReachHere(); | 147 ShouldNotReachHere(); |
142 } | 148 } |
143 break; | 149 break; |
150 case JVM_CONSTANT_InvokeDynamicTrans : // this tag appears only in old classfiles | |
144 case JVM_CONSTANT_InvokeDynamic : | 151 case JVM_CONSTANT_InvokeDynamic : |
145 { | 152 { |
146 if (!EnableInvokeDynamic || | 153 if (!EnableInvokeDynamic || |
147 _major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { | 154 _major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { |
148 classfile_parse_error( | 155 classfile_parse_error( |
149 (!EnableInvokeDynamic ? | 156 (!EnableInvokeDynamic ? |
150 "This JVM does not support constant tag %u in class file %s" : | 157 "This JVM does not support constant tag %u in class file %s" : |
151 "Class file version does not support constant tag %u in class file %s"), | 158 "Class file version does not support constant tag %u in class file %s"), |
152 tag, CHECK); | 159 tag, CHECK); |
153 } | 160 } |
154 cfs->guarantee_more(5, CHECK); // bsm_index, name_and_type_index, tag/access_flags | 161 if (!AllowTransitionalJSR292 && tag == JVM_CONSTANT_InvokeDynamicTrans) { |
162 classfile_parse_error( | |
163 "This JVM does not support transitional InvokeDynamic tag %u in class file %s", | |
164 tag, CHECK); | |
165 } | |
166 bool trans_no_argc = AllowTransitionalJSR292 && (tag == JVM_CONSTANT_InvokeDynamicTrans); | |
167 cfs->guarantee_more(7, CHECK); // bsm_index, nt, argc, ..., tag/access_flags | |
155 u2 bootstrap_method_index = cfs->get_u2_fast(); | 168 u2 bootstrap_method_index = cfs->get_u2_fast(); |
156 u2 name_and_type_index = cfs->get_u2_fast(); | 169 u2 name_and_type_index = cfs->get_u2_fast(); |
157 cp->invoke_dynamic_at_put(index, bootstrap_method_index, name_and_type_index); | 170 int argument_count = trans_no_argc ? 0 : cfs->get_u2_fast(); |
171 cfs->guarantee_more(2*argument_count + 1, CHECK); // argv[argc]..., tag/access_flags | |
172 int argv_offset = constantPoolOopDesc::_indy_argv_offset; | |
173 int op_count = argv_offset + argument_count; // bsm, nt, argc, argv[]... | |
174 int op_base = start_operand_group(operands, op_count, CHECK); | |
175 assert(argv_offset == 3, "else adjust next 3 assignments"); | |
176 operands->at_put(op_base + constantPoolOopDesc::_indy_bsm_offset, bootstrap_method_index); | |
177 operands->at_put(op_base + constantPoolOopDesc::_indy_nt_offset, name_and_type_index); | |
178 operands->at_put(op_base + constantPoolOopDesc::_indy_argc_offset, argument_count); | |
179 for (int arg_i = 0; arg_i < argument_count; arg_i++) { | |
180 int arg = cfs->get_u2_fast(); | |
181 operands->at_put(op_base + constantPoolOopDesc::_indy_argv_offset + arg_i, arg); | |
182 } | |
183 cp->invoke_dynamic_at_put(index, op_base, op_count); | |
184 #ifdef ASSERT | |
185 // Record the steps just taken for later checking. | |
186 indy_instructions->append(index); | |
187 indy_instructions->append(bootstrap_method_index); | |
188 indy_instructions->append(name_and_type_index); | |
189 indy_instructions->append(argument_count); | |
190 #endif //ASSERT | |
158 } | 191 } |
159 break; | 192 break; |
160 case JVM_CONSTANT_Integer : | 193 case JVM_CONSTANT_Integer : |
161 { | 194 { |
162 cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags | 195 cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags |
255 // Allocate the remaining symbols | 288 // Allocate the remaining symbols |
256 if (names_count > 0) { | 289 if (names_count > 0) { |
257 oopFactory::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); | 290 oopFactory::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); |
258 } | 291 } |
259 | 292 |
293 if (operands != NULL && operands->length() > 0) { | |
294 store_operand_array(operands, cp, CHECK); | |
295 } | |
296 #ifdef ASSERT | |
297 // Re-assert the indy structures, now that assertion checking can work. | |
298 for (int indy_i = 0; indy_i < indy_instructions->length(); ) { | |
299 int index = indy_instructions->at(indy_i++); | |
300 int bootstrap_method_index = indy_instructions->at(indy_i++); | |
301 int name_and_type_index = indy_instructions->at(indy_i++); | |
302 int argument_count = indy_instructions->at(indy_i++); | |
303 assert(cp->check_invoke_dynamic_at(index, | |
304 bootstrap_method_index, name_and_type_index, | |
305 argument_count), | |
306 "indy structure is OK"); | |
307 } | |
308 #endif //ASSERT | |
309 | |
260 // Copy _current pointer of local copy back to stream(). | 310 // Copy _current pointer of local copy back to stream(). |
261 #ifdef ASSERT | 311 #ifdef ASSERT |
262 assert(cfs0->current() == old_current, "non-exclusive use of stream()"); | 312 assert(cfs0->current() == old_current, "non-exclusive use of stream()"); |
263 #endif | 313 #endif |
264 cfs0->set_current(cfs1.current()); | 314 cfs0->set_current(cfs1.current()); |
265 } | 315 } |
316 | |
317 int ClassFileParser::start_operand_group(GrowableArray<int>* &operands, int op_count, TRAPS) { | |
318 if (operands == NULL) { | |
319 operands = new GrowableArray<int>(THREAD, 100); | |
320 int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset; | |
321 while (operands->length() <= fillp_offset) | |
322 operands->append(0); // force op_base > 0, for an error check | |
323 DEBUG_ONLY(operands->at_put(fillp_offset, (int)badHeapWordVal)); | |
324 } | |
325 int cnt_pos = operands->append(op_count); | |
326 int arg_pos = operands->length(); | |
327 operands->at_grow(arg_pos + op_count - 1); // grow to include the operands | |
328 assert(operands->length() == arg_pos + op_count, ""); | |
329 int op_base = cnt_pos - constantPoolOopDesc::_multi_operand_count_offset; | |
330 return op_base; | |
331 } | |
332 | |
333 void ClassFileParser::store_operand_array(GrowableArray<int>* operands, constantPoolHandle cp, TRAPS) { | |
334 // Collect the buffer of operands from variable-sized entries into a permanent array. | |
335 int arraylen = operands->length(); | |
336 int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset; | |
337 assert(operands->at(fillp_offset) == (int)badHeapWordVal, "value unused so far"); | |
338 operands->at_put(fillp_offset, arraylen); | |
339 cp->multi_operand_buffer_grow(arraylen, CHECK); | |
340 typeArrayOop operands_oop = cp->operands(); | |
341 assert(operands_oop->length() == arraylen, ""); | |
342 for (int i = 0; i < arraylen; i++) { | |
343 operands_oop->int_at_put(i, operands->at(i)); | |
344 } | |
345 cp->set_operands(operands_oop); | |
346 // The fill_pointer is used only by constantPoolOop::copy_entry_to and friends, | |
347 // when constant pools need to be merged. Make sure it is sane now. | |
348 assert(cp->multi_operand_buffer_fill_pointer() == arraylen, ""); | |
349 } | |
350 | |
266 | 351 |
267 bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); } | 352 bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); } |
268 | 353 |
269 constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { | 354 constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { |
270 ClassFileStream* cfs = stream(); | 355 ClassFileStream* cfs = stream(); |
429 EnableMethodHandles, | 514 EnableMethodHandles, |
430 "Invalid constant pool index %u in class file %s", | 515 "Invalid constant pool index %u in class file %s", |
431 ref_index, CHECK_(nullHandle)); | 516 ref_index, CHECK_(nullHandle)); |
432 } | 517 } |
433 break; | 518 break; |
519 case JVM_CONSTANT_InvokeDynamicTrans : | |
520 ShouldNotReachHere(); // this tag does not appear in the heap | |
434 case JVM_CONSTANT_InvokeDynamic : | 521 case JVM_CONSTANT_InvokeDynamic : |
435 { | 522 { |
436 int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index); | 523 int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index); |
437 int name_and_type_ref_index = cp->invoke_dynamic_name_and_type_ref_index_at(index); | 524 int name_and_type_ref_index = cp->invoke_dynamic_name_and_type_ref_index_at(index); |
438 check_property((bootstrap_method_ref_index == 0 && AllowTransitionalJSR292) | 525 check_property((bootstrap_method_ref_index == 0 && AllowTransitionalJSR292) |
439 || | 526 || |
440 (valid_cp_range(bootstrap_method_ref_index, length) && | 527 (valid_cp_range(bootstrap_method_ref_index, length) && |
441 cp->tag_at(bootstrap_method_ref_index).is_method_handle()), | 528 (cp->tag_at(bootstrap_method_ref_index).is_method_handle())), |
442 "Invalid constant pool index %u in class file %s", | 529 "Invalid constant pool index %u in class file %s", |
443 bootstrap_method_ref_index, | 530 bootstrap_method_ref_index, |
444 CHECK_(nullHandle)); | 531 CHECK_(nullHandle)); |
445 check_property(valid_cp_range(name_and_type_ref_index, length) && | 532 check_property(valid_cp_range(name_and_type_ref_index, length) && |
446 cp->tag_at(name_and_type_ref_index).is_name_and_type(), | 533 cp->tag_at(name_and_type_ref_index).is_name_and_type(), |
447 "Invalid constant pool index %u in class file %s", | 534 "Invalid constant pool index %u in class file %s", |
448 name_and_type_ref_index, | 535 name_and_type_ref_index, |
449 CHECK_(nullHandle)); | 536 CHECK_(nullHandle)); |
537 int argc = cp->invoke_dynamic_argument_count_at(index); | |
538 for (int arg_i = 0; arg_i < argc; arg_i++) { | |
539 int arg = cp->invoke_dynamic_argument_index_at(index, arg_i); | |
540 check_property(valid_cp_range(arg, length) && | |
541 cp->tag_at(arg).is_loadable_constant() || | |
542 // temporary early forms of string and class: | |
543 cp->tag_at(arg).is_klass_index() || | |
544 cp->tag_at(arg).is_string_index(), | |
545 "Invalid constant pool index %u in class file %s", | |
546 arg, | |
547 CHECK_(nullHandle)); | |
548 } | |
450 break; | 549 break; |
451 } | 550 } |
452 default: | 551 default: |
453 fatal(err_msg("bad constant pool tag value %u", | 552 fatal(err_msg("bad constant pool tag value %u", |
454 cp->tag_at(index).value())); | 553 cp->tag_at(index).value())); |
2514 // | 2613 // |
2515 // Check the fields in java.lang.ref.Reference for the "discovered" | 2614 // Check the fields in java.lang.ref.Reference for the "discovered" |
2516 // field. If it is not present, artifically create a field for it. | 2615 // field. If it is not present, artifically create a field for it. |
2517 // This allows this VM to run on early JDK where the field is not | 2616 // This allows this VM to run on early JDK where the field is not |
2518 // present. | 2617 // present. |
2519 | |
2520 // | |
2521 // Increment fac.nonstatic_oop_count so that the start of the | |
2522 // next type of non-static oops leaves room for the fake oop. | |
2523 // Do not increment next_nonstatic_oop_offset so that the | |
2524 // fake oop is place after the java.lang.ref.Reference oop | |
2525 // fields. | |
2526 // | |
2527 // Check the fields in java.lang.ref.Reference for the "discovered" | |
2528 // field. If it is not present, artifically create a field for it. | |
2529 // This allows this VM to run on early JDK where the field is not | |
2530 // present. | |
2531 int reference_sig_index = 0; | 2618 int reference_sig_index = 0; |
2532 int reference_name_index = 0; | 2619 int reference_name_index = 0; |
2533 int reference_index = 0; | 2620 int reference_index = 0; |
2534 int extra = java_lang_ref_Reference::number_of_fake_oop_fields; | 2621 int extra = java_lang_ref_Reference::number_of_fake_oop_fields; |
2535 const int n = (*fields_ptr)()->length(); | 2622 const int n = (*fields_ptr)()->length(); |
2661 | 2748 |
2662 | 2749 |
2663 // Force MethodHandle.vmentry to be an unmanaged pointer. | 2750 // Force MethodHandle.vmentry to be an unmanaged pointer. |
2664 // There is no way for a classfile to express this, so we must help it. | 2751 // There is no way for a classfile to express this, so we must help it. |
2665 void ClassFileParser::java_dyn_MethodHandle_fix_pre(constantPoolHandle cp, | 2752 void ClassFileParser::java_dyn_MethodHandle_fix_pre(constantPoolHandle cp, |
2666 typeArrayHandle* fields_ptr, | 2753 typeArrayHandle fields, |
2667 FieldAllocationCount *fac_ptr, | 2754 FieldAllocationCount *fac_ptr, |
2668 TRAPS) { | 2755 TRAPS) { |
2669 // Add fake fields for java.dyn.MethodHandle instances | 2756 // Add fake fields for java.dyn.MethodHandle instances |
2670 // | 2757 // |
2671 // This is not particularly nice, but since there is no way to express | 2758 // This is not particularly nice, but since there is no way to express |
2685 | 2772 |
2686 if (word_sig_index == 0) | 2773 if (word_sig_index == 0) |
2687 THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), | 2774 THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), |
2688 "missing I or J signature (for vmentry) in java.dyn.MethodHandle"); | 2775 "missing I or J signature (for vmentry) in java.dyn.MethodHandle"); |
2689 | 2776 |
2777 // Find vmentry field and change the signature. | |
2690 bool found_vmentry = false; | 2778 bool found_vmentry = false; |
2691 | 2779 for (int i = 0; i < fields->length(); i += instanceKlass::next_offset) { |
2692 const int n = (*fields_ptr)()->length(); | 2780 int name_index = fields->ushort_at(i + instanceKlass::name_index_offset); |
2693 for (int i = 0; i < n; i += instanceKlass::next_offset) { | 2781 int sig_index = fields->ushort_at(i + instanceKlass::signature_index_offset); |
2694 int name_index = (*fields_ptr)->ushort_at(i + instanceKlass::name_index_offset); | 2782 int acc_flags = fields->ushort_at(i + instanceKlass::access_flags_offset); |
2695 int sig_index = (*fields_ptr)->ushort_at(i + instanceKlass::signature_index_offset); | |
2696 int acc_flags = (*fields_ptr)->ushort_at(i + instanceKlass::access_flags_offset); | |
2697 symbolOop f_name = cp->symbol_at(name_index); | 2783 symbolOop f_name = cp->symbol_at(name_index); |
2698 symbolOop f_sig = cp->symbol_at(sig_index); | 2784 symbolOop f_sig = cp->symbol_at(sig_index); |
2699 if (f_sig == vmSymbols::byte_signature() && | 2785 |
2700 f_name == vmSymbols::vmentry_name() && | 2786 if (f_name == vmSymbols::vmentry_name() && (acc_flags & JVM_ACC_STATIC) == 0) { |
2701 (acc_flags & JVM_ACC_STATIC) == 0) { | 2787 if (f_sig == vmSymbols::machine_word_signature()) { |
2702 // Adjust the field type from byte to an unmanaged pointer. | 2788 // If the signature of vmentry is already changed, we're done. |
2703 assert(fac_ptr->nonstatic_byte_count > 0, ""); | 2789 found_vmentry = true; |
2704 fac_ptr->nonstatic_byte_count -= 1; | 2790 break; |
2705 | 2791 } |
2706 (*fields_ptr)->ushort_at_put(i + instanceKlass::signature_index_offset, word_sig_index); | 2792 else if (f_sig == vmSymbols::byte_signature()) { |
2707 assert(wordSize == longSize || wordSize == jintSize, "ILP32 or LP64"); | 2793 // Adjust the field type from byte to an unmanaged pointer. |
2708 if (wordSize == longSize) fac_ptr->nonstatic_double_count += 1; | 2794 assert(fac_ptr->nonstatic_byte_count > 0, ""); |
2709 else fac_ptr->nonstatic_word_count += 1; | 2795 fac_ptr->nonstatic_byte_count -= 1; |
2710 | 2796 |
2711 FieldAllocationType atype = (FieldAllocationType) (*fields_ptr)->ushort_at(i + instanceKlass::low_offset); | 2797 fields->ushort_at_put(i + instanceKlass::signature_index_offset, word_sig_index); |
2712 assert(atype == NONSTATIC_BYTE, ""); | 2798 assert(wordSize == longSize || wordSize == jintSize, "ILP32 or LP64"); |
2713 FieldAllocationType new_atype = (wordSize == longSize) ? NONSTATIC_DOUBLE : NONSTATIC_WORD; | 2799 if (wordSize == longSize) fac_ptr->nonstatic_double_count += 1; |
2714 (*fields_ptr)->ushort_at_put(i + instanceKlass::low_offset, new_atype); | 2800 else fac_ptr->nonstatic_word_count += 1; |
2715 | 2801 |
2716 found_vmentry = true; | 2802 FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i + instanceKlass::low_offset); |
2717 break; | 2803 assert(atype == NONSTATIC_BYTE, ""); |
2804 FieldAllocationType new_atype = (wordSize == longSize) ? NONSTATIC_DOUBLE : NONSTATIC_WORD; | |
2805 fields->ushort_at_put(i + instanceKlass::low_offset, new_atype); | |
2806 | |
2807 found_vmentry = true; | |
2808 break; | |
2809 } | |
2718 } | 2810 } |
2719 } | 2811 } |
2720 | 2812 |
2721 if (!found_vmentry) | 2813 if (!found_vmentry) |
2722 THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), | 2814 THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), |
2723 "missing vmentry byte field in java.dyn.MethodHandle"); | 2815 "missing vmentry byte field in java.dyn.MethodHandle"); |
2724 | |
2725 } | 2816 } |
2726 | 2817 |
2727 | 2818 |
2728 instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, | 2819 instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, |
2729 Handle class_loader, | 2820 Handle class_loader, |
3080 java_lang_Class_fix_pre(&methods, &fac, CHECK_(nullHandle)); | 3171 java_lang_Class_fix_pre(&methods, &fac, CHECK_(nullHandle)); |
3081 } | 3172 } |
3082 | 3173 |
3083 // adjust the vmentry field declaration in java.dyn.MethodHandle | 3174 // adjust the vmentry field declaration in java.dyn.MethodHandle |
3084 if (EnableMethodHandles && class_name() == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) { | 3175 if (EnableMethodHandles && class_name() == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) { |
3085 java_dyn_MethodHandle_fix_pre(cp, &fields, &fac, CHECK_(nullHandle)); | 3176 java_dyn_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); |
3086 } | 3177 } |
3087 | 3178 |
3088 // Add a fake "discovered" field if it is not present | 3179 // Add a fake "discovered" field if it is not present |
3089 // for compatibility with earlier jdk's. | 3180 // for compatibility with earlier jdk's. |
3090 if (class_name() == vmSymbols::java_lang_ref_Reference() | 3181 if (class_name() == vmSymbols::java_lang_ref_Reference() |