comparison src/share/vm/prims/jvmtiRedefineClasses.cpp @ 10151:15a99ca4ee34

8007037: JSR 292: the VM_RedefineClasses::append_entry() should do cross-checks with indy operands Summary: References from operands to CP entries and back must be correct after CP merge Reviewed-by: coleenp, twisti Contributed-by: serguei.spitsyn@oracle.com
author sspitsyn
date Thu, 25 Apr 2013 03:58:53 -0700
parents 6337ca4dcad8
children 712a1e9c91f3
comparison
equal deleted inserted replaced
10150:d66a24adbe3f 10151:15a99ca4ee34
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
1084 break; 1233 break;
1085 } 1234 }
1086 } // end for each old_cp entry 1235 } // end for each old_cp entry
1087 1236
1088 ConstantPool::copy_operands(old_cp, *merge_cp_p, CHECK_0); 1237 ConstantPool::copy_operands(old_cp, *merge_cp_p, CHECK_0);
1238 (*merge_cp_p)->extend_operands(scratch_cp, CHECK_0);
1089 1239
1090 // We don't need to sanity check that *merge_cp_length_p is within 1240 // We don't need to sanity check that *merge_cp_length_p is within
1091 // *merge_cp_p bounds since we have the minimum on-entry check above. 1241 // *merge_cp_p bounds since we have the minimum on-entry check above.
1092 (*merge_cp_length_p) = old_i; 1242 (*merge_cp_length_p) = old_i;
1093 } 1243 }
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);
1397 return false; 1554 return false;
1398 } 1555 }
1399 1556
1400 return true; 1557 return true;
1401 } // end rewrite_cp_refs() 1558 } // end rewrite_cp_refs()
1402
1403 1559
1404 // Rewrite constant pool references in the methods. 1560 // Rewrite constant pool references in the methods.
1405 bool VM_RedefineClasses::rewrite_cp_refs_in_methods( 1561 bool VM_RedefineClasses::rewrite_cp_refs_in_methods(
1406 instanceKlassHandle scratch_class, TRAPS) { 1562 instanceKlassHandle scratch_class, TRAPS) {
1407 1563