Mercurial > hg > graal-jvmci-8
comparison src/share/vm/classfile/classFileParser.cpp @ 2011:dad31fc330cd
7001379: bootstrap method data needs to be moved from constant pool to a classfile attribute
Reviewed-by: twisti
author | jrose |
---|---|
date | Fri, 03 Dec 2010 15:53:57 -0800 |
parents | f95d63e2154a |
children | ef3c5db0b3ae |
comparison
equal
deleted
inserted
replaced
2010:7601ab0e1e33 | 2011:dad31fc330cd |
---|---|
97 int lengths[SymbolTable::symbol_alloc_batch_size]; | 97 int lengths[SymbolTable::symbol_alloc_batch_size]; |
98 int indices[SymbolTable::symbol_alloc_batch_size]; | 98 int indices[SymbolTable::symbol_alloc_batch_size]; |
99 unsigned int hashValues[SymbolTable::symbol_alloc_batch_size]; | 99 unsigned int hashValues[SymbolTable::symbol_alloc_batch_size]; |
100 int names_count = 0; | 100 int names_count = 0; |
101 | 101 |
102 // Side buffer for operands of variable-sized (InvokeDynamic) entries. | |
103 GrowableArray<int>* operands = NULL; | |
104 #ifdef ASSERT | |
105 GrowableArray<int>* indy_instructions = new GrowableArray<int>(THREAD, 10); | |
106 #endif | |
107 | |
108 // parsing Index 0 is unused | 102 // parsing Index 0 is unused |
109 for (int index = 1; index < length; index++) { | 103 for (int index = 1; index < length; index++) { |
110 // Each of the following case guarantees one more byte in the stream | 104 // Each of the following case guarantees one more byte in the stream |
111 // for the following tag or the access_flags following constant pool, | 105 // for the following tag or the access_flags following constant pool, |
112 // so we don't need bounds-check for reading tag. | 106 // so we don't need bounds-check for reading tag. |
182 (!EnableInvokeDynamic ? | 176 (!EnableInvokeDynamic ? |
183 "This JVM does not support constant tag %u in class file %s" : | 177 "This JVM does not support constant tag %u in class file %s" : |
184 "Class file version does not support constant tag %u in class file %s"), | 178 "Class file version does not support constant tag %u in class file %s"), |
185 tag, CHECK); | 179 tag, CHECK); |
186 } | 180 } |
187 if (!AllowTransitionalJSR292 && tag == JVM_CONSTANT_InvokeDynamicTrans) { | 181 cfs->guarantee_more(5, CHECK); // bsm_index, nt, tag/access_flags |
188 classfile_parse_error( | 182 u2 bootstrap_specifier_index = cfs->get_u2_fast(); |
183 u2 name_and_type_index = cfs->get_u2_fast(); | |
184 if (tag == JVM_CONSTANT_InvokeDynamicTrans) { | |
185 if (!AllowTransitionalJSR292) | |
186 classfile_parse_error( | |
189 "This JVM does not support transitional InvokeDynamic tag %u in class file %s", | 187 "This JVM does not support transitional InvokeDynamic tag %u in class file %s", |
190 tag, CHECK); | 188 tag, CHECK); |
189 cp->invoke_dynamic_trans_at_put(index, bootstrap_specifier_index, name_and_type_index); | |
190 break; | |
191 } | 191 } |
192 bool trans_no_argc = AllowTransitionalJSR292 && (tag == JVM_CONSTANT_InvokeDynamicTrans); | 192 if (_max_bootstrap_specifier_index < (int) bootstrap_specifier_index) |
193 cfs->guarantee_more(7, CHECK); // bsm_index, nt, argc, ..., tag/access_flags | 193 _max_bootstrap_specifier_index = (int) bootstrap_specifier_index; // collect for later |
194 u2 bootstrap_method_index = cfs->get_u2_fast(); | 194 cp->invoke_dynamic_at_put(index, bootstrap_specifier_index, name_and_type_index); |
195 u2 name_and_type_index = cfs->get_u2_fast(); | |
196 int argument_count = trans_no_argc ? 0 : cfs->get_u2_fast(); | |
197 cfs->guarantee_more(2*argument_count + 1, CHECK); // argv[argc]..., tag/access_flags | |
198 int argv_offset = constantPoolOopDesc::_indy_argv_offset; | |
199 int op_count = argv_offset + argument_count; // bsm, nt, argc, argv[]... | |
200 int op_base = start_operand_group(operands, op_count, CHECK); | |
201 assert(argv_offset == 3, "else adjust next 3 assignments"); | |
202 operands->at_put(op_base + constantPoolOopDesc::_indy_bsm_offset, bootstrap_method_index); | |
203 operands->at_put(op_base + constantPoolOopDesc::_indy_nt_offset, name_and_type_index); | |
204 operands->at_put(op_base + constantPoolOopDesc::_indy_argc_offset, argument_count); | |
205 for (int arg_i = 0; arg_i < argument_count; arg_i++) { | |
206 int arg = cfs->get_u2_fast(); | |
207 operands->at_put(op_base + constantPoolOopDesc::_indy_argv_offset + arg_i, arg); | |
208 } | |
209 cp->invoke_dynamic_at_put(index, op_base, op_count); | |
210 #ifdef ASSERT | |
211 // Record the steps just taken for later checking. | |
212 indy_instructions->append(index); | |
213 indy_instructions->append(bootstrap_method_index); | |
214 indy_instructions->append(name_and_type_index); | |
215 indy_instructions->append(argument_count); | |
216 #endif //ASSERT | |
217 } | 195 } |
218 break; | 196 break; |
219 case JVM_CONSTANT_Integer : | 197 case JVM_CONSTANT_Integer : |
220 { | 198 { |
221 cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags | 199 cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags |
314 // Allocate the remaining symbols | 292 // Allocate the remaining symbols |
315 if (names_count > 0) { | 293 if (names_count > 0) { |
316 oopFactory::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); | 294 oopFactory::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); |
317 } | 295 } |
318 | 296 |
319 if (operands != NULL && operands->length() > 0) { | |
320 store_operand_array(operands, cp, CHECK); | |
321 } | |
322 #ifdef ASSERT | |
323 // Re-assert the indy structures, now that assertion checking can work. | |
324 for (int indy_i = 0; indy_i < indy_instructions->length(); ) { | |
325 int index = indy_instructions->at(indy_i++); | |
326 int bootstrap_method_index = indy_instructions->at(indy_i++); | |
327 int name_and_type_index = indy_instructions->at(indy_i++); | |
328 int argument_count = indy_instructions->at(indy_i++); | |
329 assert(cp->check_invoke_dynamic_at(index, | |
330 bootstrap_method_index, name_and_type_index, | |
331 argument_count), | |
332 "indy structure is OK"); | |
333 } | |
334 #endif //ASSERT | |
335 | |
336 // Copy _current pointer of local copy back to stream(). | 297 // Copy _current pointer of local copy back to stream(). |
337 #ifdef ASSERT | 298 #ifdef ASSERT |
338 assert(cfs0->current() == old_current, "non-exclusive use of stream()"); | 299 assert(cfs0->current() == old_current, "non-exclusive use of stream()"); |
339 #endif | 300 #endif |
340 cfs0->set_current(cfs1.current()); | 301 cfs0->set_current(cfs1.current()); |
341 } | 302 } |
342 | |
343 int ClassFileParser::start_operand_group(GrowableArray<int>* &operands, int op_count, TRAPS) { | |
344 if (operands == NULL) { | |
345 operands = new GrowableArray<int>(THREAD, 100); | |
346 int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset; | |
347 while (operands->length() <= fillp_offset) | |
348 operands->append(0); // force op_base > 0, for an error check | |
349 DEBUG_ONLY(operands->at_put(fillp_offset, (int)badHeapWordVal)); | |
350 } | |
351 int cnt_pos = operands->append(op_count); | |
352 int arg_pos = operands->length(); | |
353 operands->at_grow(arg_pos + op_count - 1); // grow to include the operands | |
354 assert(operands->length() == arg_pos + op_count, ""); | |
355 int op_base = cnt_pos - constantPoolOopDesc::_multi_operand_count_offset; | |
356 return op_base; | |
357 } | |
358 | |
359 void ClassFileParser::store_operand_array(GrowableArray<int>* operands, constantPoolHandle cp, TRAPS) { | |
360 // Collect the buffer of operands from variable-sized entries into a permanent array. | |
361 int arraylen = operands->length(); | |
362 int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset; | |
363 assert(operands->at(fillp_offset) == (int)badHeapWordVal, "value unused so far"); | |
364 operands->at_put(fillp_offset, arraylen); | |
365 cp->multi_operand_buffer_grow(arraylen, CHECK); | |
366 typeArrayOop operands_oop = cp->operands(); | |
367 assert(operands_oop->length() == arraylen, ""); | |
368 for (int i = 0; i < arraylen; i++) { | |
369 operands_oop->int_at_put(i, operands->at(i)); | |
370 } | |
371 cp->set_operands(operands_oop); | |
372 // The fill_pointer is used only by constantPoolOop::copy_entry_to and friends, | |
373 // when constant pools need to be merged. Make sure it is sane now. | |
374 assert(cp->multi_operand_buffer_fill_pointer() == arraylen, ""); | |
375 } | |
376 | |
377 | 303 |
378 bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); } | 304 bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); } |
379 | 305 |
380 constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { | 306 constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { |
381 ClassFileStream* cfs = stream(); | 307 ClassFileStream* cfs = stream(); |
399 | 325 |
400 int index = 1; // declared outside of loops for portability | 326 int index = 1; // declared outside of loops for portability |
401 | 327 |
402 // first verification pass - validate cross references and fixup class and string constants | 328 // first verification pass - validate cross references and fixup class and string constants |
403 for (index = 1; index < length; index++) { // Index 0 is unused | 329 for (index = 1; index < length; index++) { // Index 0 is unused |
404 switch (cp->tag_at(index).value()) { | 330 jbyte tag = cp->tag_at(index).value(); |
331 switch (tag) { | |
405 case JVM_CONSTANT_Class : | 332 case JVM_CONSTANT_Class : |
406 ShouldNotReachHere(); // Only JVM_CONSTANT_ClassIndex should be present | 333 ShouldNotReachHere(); // Only JVM_CONSTANT_ClassIndex should be present |
407 break; | 334 break; |
408 case JVM_CONSTANT_Fieldref : | 335 case JVM_CONSTANT_Fieldref : |
409 // fall through | 336 // fall through |
541 "Invalid constant pool index %u in class file %s", | 468 "Invalid constant pool index %u in class file %s", |
542 ref_index, CHECK_(nullHandle)); | 469 ref_index, CHECK_(nullHandle)); |
543 } | 470 } |
544 break; | 471 break; |
545 case JVM_CONSTANT_InvokeDynamicTrans : | 472 case JVM_CONSTANT_InvokeDynamicTrans : |
546 ShouldNotReachHere(); // this tag does not appear in the heap | |
547 case JVM_CONSTANT_InvokeDynamic : | 473 case JVM_CONSTANT_InvokeDynamic : |
548 { | 474 { |
549 int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index); | |
550 int name_and_type_ref_index = cp->invoke_dynamic_name_and_type_ref_index_at(index); | 475 int name_and_type_ref_index = cp->invoke_dynamic_name_and_type_ref_index_at(index); |
551 check_property((bootstrap_method_ref_index == 0 && AllowTransitionalJSR292) | |
552 || | |
553 (valid_cp_range(bootstrap_method_ref_index, length) && | |
554 (cp->tag_at(bootstrap_method_ref_index).is_method_handle())), | |
555 "Invalid constant pool index %u in class file %s", | |
556 bootstrap_method_ref_index, | |
557 CHECK_(nullHandle)); | |
558 check_property(valid_cp_range(name_and_type_ref_index, length) && | 476 check_property(valid_cp_range(name_and_type_ref_index, length) && |
559 cp->tag_at(name_and_type_ref_index).is_name_and_type(), | 477 cp->tag_at(name_and_type_ref_index).is_name_and_type(), |
560 "Invalid constant pool index %u in class file %s", | 478 "Invalid constant pool index %u in class file %s", |
561 name_and_type_ref_index, | 479 name_and_type_ref_index, |
562 CHECK_(nullHandle)); | 480 CHECK_(nullHandle)); |
563 int argc = cp->invoke_dynamic_argument_count_at(index); | 481 if (tag == JVM_CONSTANT_InvokeDynamicTrans) { |
564 for (int arg_i = 0; arg_i < argc; arg_i++) { | 482 int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index); |
565 int arg = cp->invoke_dynamic_argument_index_at(index, arg_i); | 483 check_property(valid_cp_range(bootstrap_method_ref_index, length) && |
566 check_property(valid_cp_range(arg, length) && | 484 cp->tag_at(bootstrap_method_ref_index).is_method_handle(), |
567 cp->tag_at(arg).is_loadable_constant() || | |
568 // temporary early forms of string and class: | |
569 cp->tag_at(arg).is_klass_index() || | |
570 cp->tag_at(arg).is_string_index(), | |
571 "Invalid constant pool index %u in class file %s", | 485 "Invalid constant pool index %u in class file %s", |
572 arg, | 486 bootstrap_method_ref_index, |
573 CHECK_(nullHandle)); | 487 CHECK_(nullHandle)); |
574 } | 488 } |
489 // bootstrap specifier index must be checked later, when BootstrapMethods attr is available | |
575 break; | 490 break; |
576 } | 491 } |
577 default: | 492 default: |
578 fatal(err_msg("bad constant pool tag value %u", | 493 fatal(err_msg("bad constant pool tag value %u", |
579 cp->tag_at(index).value())); | 494 cp->tag_at(index).value())); |
2427 "Invalid constant pool index %u in Signature attribute in class file %s", | 2342 "Invalid constant pool index %u in Signature attribute in class file %s", |
2428 signature_index, CHECK); | 2343 signature_index, CHECK); |
2429 k->set_generic_signature(cp->symbol_at(signature_index)); | 2344 k->set_generic_signature(cp->symbol_at(signature_index)); |
2430 } | 2345 } |
2431 | 2346 |
2347 void ClassFileParser::parse_classfile_bootstrap_methods_attribute(constantPoolHandle cp, instanceKlassHandle k, | |
2348 u4 attribute_byte_length, TRAPS) { | |
2349 ClassFileStream* cfs = stream(); | |
2350 u1* current_start = cfs->current(); | |
2351 | |
2352 cfs->guarantee_more(2, CHECK); // length | |
2353 int attribute_array_length = cfs->get_u2_fast(); | |
2354 | |
2355 guarantee_property(_max_bootstrap_specifier_index < attribute_array_length, | |
2356 "Short length on BootstrapMethods in class file %s", | |
2357 CHECK); | |
2358 | |
2359 // The attribute contains a counted array of counted tuples of shorts, | |
2360 // represending bootstrap specifiers: | |
2361 // length*{bootstrap_method_index, argument_count*{argument_index}} | |
2362 int operand_count = (attribute_byte_length - sizeof(u2)) / sizeof(u2); | |
2363 // operand_count = number of shorts in attr, except for leading length | |
2364 | |
2365 // The attribute is copied into a short[] array. | |
2366 // The array begins with a series of short[2] pairs, one for each tuple. | |
2367 int index_size = (attribute_array_length * 2); | |
2368 | |
2369 typeArrayOop operands_oop = oopFactory::new_permanent_intArray(index_size + operand_count, CHECK); | |
2370 typeArrayHandle operands(THREAD, operands_oop); | |
2371 operands_oop = NULL; // tidy | |
2372 | |
2373 int operand_fill_index = index_size; | |
2374 int cp_size = cp->length(); | |
2375 | |
2376 for (int n = 0; n < attribute_array_length; n++) { | |
2377 // Store a 32-bit offset into the header of the operand array. | |
2378 assert(constantPoolOopDesc::operand_offset_at(operands(), n) == 0, ""); | |
2379 constantPoolOopDesc::operand_offset_at_put(operands(), n, operand_fill_index); | |
2380 | |
2381 // Read a bootstrap specifier. | |
2382 cfs->guarantee_more(sizeof(u2) * 2, CHECK); // bsm, argc | |
2383 u2 bootstrap_method_index = cfs->get_u2_fast(); | |
2384 u2 argument_count = cfs->get_u2_fast(); | |
2385 check_property( | |
2386 valid_cp_range(bootstrap_method_index, cp_size) && | |
2387 cp->tag_at(bootstrap_method_index).is_method_handle(), | |
2388 "bootstrap_method_index %u has bad constant type in class file %s", | |
2389 CHECK); | |
2390 operands->short_at_put(operand_fill_index++, bootstrap_method_index); | |
2391 operands->short_at_put(operand_fill_index++, argument_count); | |
2392 | |
2393 cfs->guarantee_more(sizeof(u2) * argument_count, CHECK); // argv[argc] | |
2394 for (int j = 0; j < argument_count; j++) { | |
2395 u2 arg_index = cfs->get_u2_fast(); | |
2396 check_property( | |
2397 valid_cp_range(arg_index, cp_size) && | |
2398 cp->tag_at(arg_index).is_loadable_constant(), | |
2399 "argument_index %u has bad constant type in class file %s", | |
2400 CHECK); | |
2401 operands->short_at_put(operand_fill_index++, arg_index); | |
2402 } | |
2403 } | |
2404 | |
2405 assert(operand_fill_index == operands()->length(), "exact fill"); | |
2406 assert(constantPoolOopDesc::operand_array_length(operands()) == attribute_array_length, "correct decode"); | |
2407 | |
2408 u1* current_end = cfs->current(); | |
2409 guarantee_property(current_end == current_start + attribute_byte_length, | |
2410 "Bad length on BootstrapMethods in class file %s", | |
2411 CHECK); | |
2412 | |
2413 cp->set_operands(operands()); | |
2414 } | |
2415 | |
2416 | |
2432 void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS) { | 2417 void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS) { |
2433 ClassFileStream* cfs = stream(); | 2418 ClassFileStream* cfs = stream(); |
2434 // Set inner classes attribute to default sentinel | 2419 // Set inner classes attribute to default sentinel |
2435 k->set_inner_classes(Universe::the_empty_short_array()); | 2420 k->set_inner_classes(Universe::the_empty_short_array()); |
2436 cfs->guarantee_more(2, CHECK); // attributes_count | 2421 cfs->guarantee_more(2, CHECK); // attributes_count |
2437 u2 attributes_count = cfs->get_u2_fast(); | 2422 u2 attributes_count = cfs->get_u2_fast(); |
2438 bool parsed_sourcefile_attribute = false; | 2423 bool parsed_sourcefile_attribute = false; |
2439 bool parsed_innerclasses_attribute = false; | 2424 bool parsed_innerclasses_attribute = false; |
2440 bool parsed_enclosingmethod_attribute = false; | 2425 bool parsed_enclosingmethod_attribute = false; |
2426 bool parsed_bootstrap_methods_attribute = false; | |
2441 u1* runtime_visible_annotations = NULL; | 2427 u1* runtime_visible_annotations = NULL; |
2442 int runtime_visible_annotations_length = 0; | 2428 int runtime_visible_annotations_length = 0; |
2443 u1* runtime_invisible_annotations = NULL; | 2429 u1* runtime_invisible_annotations = NULL; |
2444 int runtime_invisible_annotations_length = 0; | 2430 int runtime_invisible_annotations_length = 0; |
2445 // Iterate over attributes | 2431 // Iterate over attributes |
2534 (!cp->is_within_bounds(method_index) || | 2520 (!cp->is_within_bounds(method_index) || |
2535 !cp->tag_at(method_index).is_name_and_type())) { | 2521 !cp->tag_at(method_index).is_name_and_type())) { |
2536 classfile_parse_error("Invalid or out-of-bounds method index in EnclosingMethod attribute in class file %s", CHECK); | 2522 classfile_parse_error("Invalid or out-of-bounds method index in EnclosingMethod attribute in class file %s", CHECK); |
2537 } | 2523 } |
2538 k->set_enclosing_method_indices(class_index, method_index); | 2524 k->set_enclosing_method_indices(class_index, method_index); |
2525 } else if (tag == vmSymbols::tag_bootstrap_methods() && | |
2526 _major_version >= Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { | |
2527 if (parsed_bootstrap_methods_attribute) | |
2528 classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", CHECK); | |
2529 parsed_bootstrap_methods_attribute = true; | |
2530 parse_classfile_bootstrap_methods_attribute(cp, k, attribute_length, CHECK); | |
2539 } else { | 2531 } else { |
2540 // Unknown attribute | 2532 // Unknown attribute |
2541 cfs->skip_u1(attribute_length, CHECK); | 2533 cfs->skip_u1(attribute_length, CHECK); |
2542 } | 2534 } |
2543 } else { | 2535 } else { |
2549 runtime_visible_annotations_length, | 2541 runtime_visible_annotations_length, |
2550 runtime_invisible_annotations, | 2542 runtime_invisible_annotations, |
2551 runtime_invisible_annotations_length, | 2543 runtime_invisible_annotations_length, |
2552 CHECK); | 2544 CHECK); |
2553 k->set_class_annotations(annotations()); | 2545 k->set_class_annotations(annotations()); |
2546 | |
2547 if (_max_bootstrap_specifier_index >= 0) { | |
2548 guarantee_property(parsed_bootstrap_methods_attribute, | |
2549 "Missing BootstrapMethods attribute in class file %s", CHECK); | |
2550 } | |
2554 } | 2551 } |
2555 | 2552 |
2556 | 2553 |
2557 typeArrayHandle ClassFileParser::assemble_annotations(u1* runtime_visible_annotations, | 2554 typeArrayHandle ClassFileParser::assemble_annotations(u1* runtime_visible_annotations, |
2558 int runtime_visible_annotations_length, | 2555 int runtime_visible_annotations_length, |
2866 jt->get_thread_stat()->perf_recursion_counts_addr(), | 2863 jt->get_thread_stat()->perf_recursion_counts_addr(), |
2867 jt->get_thread_stat()->perf_timers_addr(), | 2864 jt->get_thread_stat()->perf_timers_addr(), |
2868 PerfClassTraceTime::PARSE_CLASS); | 2865 PerfClassTraceTime::PARSE_CLASS); |
2869 | 2866 |
2870 _has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false; | 2867 _has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false; |
2868 _max_bootstrap_specifier_index = -1; | |
2871 | 2869 |
2872 if (JvmtiExport::should_post_class_file_load_hook()) { | 2870 if (JvmtiExport::should_post_class_file_load_hook()) { |
2873 unsigned char* ptr = cfs->buffer(); | 2871 unsigned char* ptr = cfs->buffer(); |
2874 unsigned char* end_ptr = cfs->buffer() + cfs->length(); | 2872 unsigned char* end_ptr = cfs->buffer() + cfs->length(); |
2875 | 2873 |