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(); |
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 { |