413 } break; |
413 } break; |
414 |
414 |
415 // this is an indirect CP entry so it needs special handling |
415 // this is an indirect CP entry so it needs special handling |
416 case JVM_CONSTANT_InvokeDynamic: |
416 case JVM_CONSTANT_InvokeDynamic: |
417 { |
417 { |
418 // TBD: cross-checks and possible extra appends into CP and bsm operands |
418 // Index of the bootstrap specifier in the operands array |
419 // are needed as well. This issue is tracked by a separate bug 8007037. |
419 int old_bs_i = scratch_cp->invoke_dynamic_bootstrap_specifier_index(scratch_i); |
420 int bss_idx = scratch_cp->invoke_dynamic_bootstrap_specifier_index(scratch_i); |
420 int new_bs_i = find_or_append_operand(scratch_cp, old_bs_i, merge_cp_p, |
421 |
421 merge_cp_length_p, THREAD); |
422 int ref_i = scratch_cp->invoke_dynamic_name_and_type_ref_index_at(scratch_i); |
422 // The bootstrap method NameAndType_info index |
423 int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p, |
423 int old_ref_i = scratch_cp->invoke_dynamic_name_and_type_ref_index_at(scratch_i); |
|
424 int new_ref_i = find_or_append_indirect_entry(scratch_cp, old_ref_i, merge_cp_p, |
424 merge_cp_length_p, THREAD); |
425 merge_cp_length_p, THREAD); |
425 if (new_ref_i != ref_i) { |
426 if (new_bs_i != old_bs_i) { |
426 RC_TRACE(0x00080000, |
427 RC_TRACE(0x00080000, |
427 ("InvokeDynamic entry@%d name_and_type ref_index change: %d to %d", |
428 ("InvokeDynamic entry@%d bootstrap_method_attr_index change: %d to %d", |
428 *merge_cp_length_p, ref_i, new_ref_i)); |
429 *merge_cp_length_p, old_bs_i, new_bs_i)); |
429 } |
430 } |
430 |
431 if (new_ref_i != old_ref_i) { |
431 (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, bss_idx, new_ref_i); |
432 RC_TRACE(0x00080000, |
|
433 ("InvokeDynamic entry@%d name_and_type_index change: %d to %d", |
|
434 *merge_cp_length_p, old_ref_i, new_ref_i)); |
|
435 } |
|
436 |
|
437 (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, new_bs_i, new_ref_i); |
432 if (scratch_i != *merge_cp_length_p) { |
438 if (scratch_i != *merge_cp_length_p) { |
433 // The new entry in *merge_cp_p is at a different index than |
439 // The new entry in *merge_cp_p is at a different index than |
434 // the new entry in scratch_cp so we need to map the index values. |
440 // the new entry in scratch_cp so we need to map the index values. |
435 map_index(scratch_cp, scratch_i, *merge_cp_length_p); |
441 map_index(scratch_cp, scratch_i, *merge_cp_length_p); |
436 } |
442 } |
488 } |
494 } |
489 } |
495 } |
490 |
496 |
491 return new_ref_i; |
497 return new_ref_i; |
492 } // end find_or_append_indirect_entry() |
498 } // end find_or_append_indirect_entry() |
|
499 |
|
500 |
|
501 // Append a bootstrap specifier into the merge_cp operands that is semantically equal |
|
502 // to the scratch_cp operands bootstrap specifier passed by the old_bs_i index. |
|
503 // Recursively append new merge_cp entries referenced by the new bootstrap specifier. |
|
504 void VM_RedefineClasses::append_operand(constantPoolHandle scratch_cp, int old_bs_i, |
|
505 constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) { |
|
506 |
|
507 int old_ref_i = scratch_cp->operand_bootstrap_method_ref_index_at(old_bs_i); |
|
508 int new_ref_i = find_or_append_indirect_entry(scratch_cp, old_ref_i, merge_cp_p, |
|
509 merge_cp_length_p, THREAD); |
|
510 if (new_ref_i != old_ref_i) { |
|
511 RC_TRACE(0x00080000, |
|
512 ("operands entry@%d bootstrap method ref_index change: %d to %d", |
|
513 _operands_cur_length, old_ref_i, new_ref_i)); |
|
514 } |
|
515 |
|
516 Array<u2>* merge_ops = (*merge_cp_p)->operands(); |
|
517 int new_bs_i = _operands_cur_length; |
|
518 // We have _operands_cur_length == 0 when the merge_cp operands is empty yet. |
|
519 // However, the operand_offset_at(0) was set in the extend_operands() call. |
|
520 int new_base = (new_bs_i == 0) ? (*merge_cp_p)->operand_offset_at(0) |
|
521 : (*merge_cp_p)->operand_next_offset_at(new_bs_i - 1); |
|
522 int argc = scratch_cp->operand_argument_count_at(old_bs_i); |
|
523 |
|
524 ConstantPool::operand_offset_at_put(merge_ops, _operands_cur_length, new_base); |
|
525 merge_ops->at_put(new_base++, new_ref_i); |
|
526 merge_ops->at_put(new_base++, argc); |
|
527 |
|
528 for (int i = 0; i < argc; i++) { |
|
529 int old_arg_ref_i = scratch_cp->operand_argument_index_at(old_bs_i, i); |
|
530 int new_arg_ref_i = find_or_append_indirect_entry(scratch_cp, old_arg_ref_i, merge_cp_p, |
|
531 merge_cp_length_p, THREAD); |
|
532 merge_ops->at_put(new_base++, new_arg_ref_i); |
|
533 if (new_arg_ref_i != old_arg_ref_i) { |
|
534 RC_TRACE(0x00080000, |
|
535 ("operands entry@%d bootstrap method argument ref_index change: %d to %d", |
|
536 _operands_cur_length, old_arg_ref_i, new_arg_ref_i)); |
|
537 } |
|
538 } |
|
539 if (old_bs_i != _operands_cur_length) { |
|
540 // The bootstrap specifier in *merge_cp_p is at a different index than |
|
541 // that in scratch_cp so we need to map the index values. |
|
542 map_operand_index(old_bs_i, new_bs_i); |
|
543 } |
|
544 _operands_cur_length++; |
|
545 } // end append_operand() |
|
546 |
|
547 |
|
548 int VM_RedefineClasses::find_or_append_operand(constantPoolHandle scratch_cp, |
|
549 int old_bs_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) { |
|
550 |
|
551 int new_bs_i = old_bs_i; // bootstrap specifier index |
|
552 bool match = (old_bs_i < _operands_cur_length) && |
|
553 scratch_cp->compare_operand_to(old_bs_i, *merge_cp_p, old_bs_i, THREAD); |
|
554 |
|
555 if (!match) { |
|
556 // forward reference in *merge_cp_p or not a direct match |
|
557 int found_i = scratch_cp->find_matching_operand(old_bs_i, *merge_cp_p, |
|
558 _operands_cur_length, THREAD); |
|
559 if (found_i != -1) { |
|
560 guarantee(found_i != old_bs_i, "compare_operand_to() and find_matching_operand() disagree"); |
|
561 // found a matching operand somewhere else in *merge_cp_p so just need a mapping |
|
562 new_bs_i = found_i; |
|
563 map_operand_index(old_bs_i, found_i); |
|
564 } else { |
|
565 // no match found so we have to append this bootstrap specifier to *merge_cp_p |
|
566 append_operand(scratch_cp, old_bs_i, merge_cp_p, merge_cp_length_p, THREAD); |
|
567 new_bs_i = _operands_cur_length - 1; |
|
568 } |
|
569 } |
|
570 return new_bs_i; |
|
571 } // end find_or_append_operand() |
|
572 |
|
573 |
|
574 void VM_RedefineClasses::finalize_operands_merge(constantPoolHandle merge_cp, TRAPS) { |
|
575 if (merge_cp->operands() == NULL) { |
|
576 return; |
|
577 } |
|
578 // Shrink the merge_cp operands |
|
579 merge_cp->shrink_operands(_operands_cur_length, CHECK); |
|
580 |
|
581 if (RC_TRACE_ENABLED(0x00040000)) { |
|
582 // don't want to loop unless we are tracing |
|
583 int count = 0; |
|
584 for (int i = 1; i < _operands_index_map_p->length(); i++) { |
|
585 int value = _operands_index_map_p->at(i); |
|
586 if (value != -1) { |
|
587 RC_TRACE_WITH_THREAD(0x00040000, THREAD, |
|
588 ("operands_index_map[%d]: old=%d new=%d", count, i, value)); |
|
589 count++; |
|
590 } |
|
591 } |
|
592 } |
|
593 // Clean-up |
|
594 _operands_index_map_p = NULL; |
|
595 _operands_cur_length = 0; |
|
596 _operands_index_map_count = 0; |
|
597 } // end finalize_operands_merge() |
493 |
598 |
494 |
599 |
495 jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions( |
600 jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions( |
496 instanceKlassHandle the_class, |
601 instanceKlassHandle the_class, |
497 instanceKlassHandle scratch_class) { |
602 instanceKlassHandle scratch_class) { |
763 |
868 |
764 return value; |
869 return value; |
765 } // end find_new_index() |
870 } // end find_new_index() |
766 |
871 |
767 |
872 |
|
873 // Find new bootstrap specifier index value for old bootstrap specifier index |
|
874 // value by seaching the index map. Returns unused index (-1) if there is |
|
875 // no mapped value for the old bootstrap specifier index. |
|
876 int VM_RedefineClasses::find_new_operand_index(int old_index) { |
|
877 if (_operands_index_map_count == 0) { |
|
878 // map is empty so nothing can be found |
|
879 return -1; |
|
880 } |
|
881 |
|
882 if (old_index == -1 || old_index >= _operands_index_map_p->length()) { |
|
883 // The old_index is out of range so it is not mapped. |
|
884 // This should not happen in regular constant pool merging use. |
|
885 return -1; |
|
886 } |
|
887 |
|
888 int value = _operands_index_map_p->at(old_index); |
|
889 if (value == -1) { |
|
890 // the old_index is not mapped |
|
891 return -1; |
|
892 } |
|
893 |
|
894 return value; |
|
895 } // end find_new_operand_index() |
|
896 |
|
897 |
768 // Returns true if the current mismatch is due to a resolved/unresolved |
898 // Returns true if the current mismatch is due to a resolved/unresolved |
769 // class pair. Otherwise, returns false. |
899 // class pair. Otherwise, returns false. |
770 bool VM_RedefineClasses::is_unresolved_class_mismatch(constantPoolHandle cp1, |
900 bool VM_RedefineClasses::is_unresolved_class_mismatch(constantPoolHandle cp1, |
771 int index1, constantPoolHandle cp2, int index2) { |
901 int index1, constantPoolHandle cp2, int index2) { |
772 |
902 |
1012 RC_TRACE(0x00040000, ("mapped tag %d at index %d to %d", |
1142 RC_TRACE(0x00040000, ("mapped tag %d at index %d to %d", |
1013 scratch_cp->tag_at(old_index).value(), old_index, new_index)); |
1143 scratch_cp->tag_at(old_index).value(), old_index, new_index)); |
1014 } // end map_index() |
1144 } // end map_index() |
1015 |
1145 |
1016 |
1146 |
|
1147 // Map old_index to new_index as needed. |
|
1148 void VM_RedefineClasses::map_operand_index(int old_index, int new_index) { |
|
1149 if (find_new_operand_index(old_index) != -1) { |
|
1150 // old_index is already mapped |
|
1151 return; |
|
1152 } |
|
1153 |
|
1154 if (old_index == new_index) { |
|
1155 // no mapping is needed |
|
1156 return; |
|
1157 } |
|
1158 |
|
1159 _operands_index_map_p->at_put(old_index, new_index); |
|
1160 _operands_index_map_count++; |
|
1161 |
|
1162 RC_TRACE(0x00040000, ("mapped bootstrap specifier at index %d to %d", old_index, new_index)); |
|
1163 } // end map_index() |
|
1164 |
|
1165 |
1017 // Merge old_cp and scratch_cp and return the results of the merge via |
1166 // Merge old_cp and scratch_cp and return the results of the merge via |
1018 // merge_cp_p. The number of entries in *merge_cp_p is returned via |
1167 // merge_cp_p. The number of entries in *merge_cp_p is returned via |
1019 // merge_cp_length_p. The entries in old_cp occupy the same locations |
1168 // merge_cp_length_p. The entries in old_cp occupy the same locations |
1020 // in *merge_cp_p. Also creates a map of indices from entries in |
1169 // in *merge_cp_p. Also creates a map of indices from entries in |
1021 // scratch_cp to the corresponding entry in *merge_cp_p. Index map |
1170 // scratch_cp to the corresponding entry in *merge_cp_p. Index map |
1196 // referenced entries to *merge_cp_p. |
1346 // referenced entries to *merge_cp_p. |
1197 append_entry(scratch_cp, scratch_i, merge_cp_p, merge_cp_length_p, |
1347 append_entry(scratch_cp, scratch_i, merge_cp_p, merge_cp_length_p, |
1198 CHECK_0); |
1348 CHECK_0); |
1199 } |
1349 } |
1200 |
1350 |
|
1351 finalize_operands_merge(*merge_cp_p, THREAD); |
|
1352 |
1201 RC_TRACE_WITH_THREAD(0x00020000, THREAD, |
1353 RC_TRACE_WITH_THREAD(0x00020000, THREAD, |
1202 ("after pass 1b: merge_cp_len=%d, scratch_i=%d, index_map_len=%d", |
1354 ("after pass 1b: merge_cp_len=%d, scratch_i=%d, index_map_len=%d", |
1203 *merge_cp_length_p, scratch_i, _index_map_count)); |
1355 *merge_cp_length_p, scratch_i, _index_map_count)); |
1204 } |
1356 } |
1205 |
1357 |
1268 |
1420 |
1269 ResourceMark rm(THREAD); |
1421 ResourceMark rm(THREAD); |
1270 _index_map_count = 0; |
1422 _index_map_count = 0; |
1271 _index_map_p = new intArray(scratch_cp->length(), -1); |
1423 _index_map_p = new intArray(scratch_cp->length(), -1); |
1272 |
1424 |
|
1425 _operands_cur_length = ConstantPool::operand_array_length(old_cp->operands()); |
|
1426 _operands_index_map_count = 0; |
|
1427 _operands_index_map_p = new intArray( |
|
1428 ConstantPool::operand_array_length(scratch_cp->operands()), -1); |
|
1429 |
1273 // reference to the cp holder is needed for copy_operands() |
1430 // reference to the cp holder is needed for copy_operands() |
1274 merge_cp->set_pool_holder(scratch_class()); |
1431 merge_cp->set_pool_holder(scratch_class()); |
1275 bool result = merge_constant_pools(old_cp, scratch_cp, &merge_cp, |
1432 bool result = merge_constant_pools(old_cp, scratch_cp, &merge_cp, |
1276 &merge_cp_length, THREAD); |
1433 &merge_cp_length, THREAD); |
1277 merge_cp->set_pool_holder(NULL); |
1434 merge_cp->set_pool_holder(NULL); |