8005128: JSR 292: the mlvm redefineClassInBootstrap test crashes in ConstantPool::compare_entry_to
Summary: When constant pool is copied in merge_constant_pools the invokedynamic operands must be copied before.
Reviewed-by: coleenp, twisti
Contributed-by: serguei.spitsyn@oracle.com
--- a/hotspot/src/share/vm/oops/constantPool.cpp Wed Jan 23 10:34:29 2013 -0500
+++ b/hotspot/src/share/vm/oops/constantPool.cpp Thu Jan 24 22:13:32 2013 -0800
@@ -1098,32 +1098,9 @@
} // end compare_entry_to()
-// Copy this constant pool's entries at start_i to end_i (inclusive)
-// to the constant pool to_cp's entries starting at to_i. A total of
-// (end_i - start_i) + 1 entries are copied.
-void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i,
- constantPoolHandle to_cp, int to_i, TRAPS) {
-
- int dest_i = to_i; // leave original alone for debug purposes
-
- for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) {
- copy_entry_to(from_cp, src_i, to_cp, dest_i, CHECK);
-
- switch (from_cp->tag_at(src_i).value()) {
- case JVM_CONSTANT_Double:
- case JVM_CONSTANT_Long:
- // double and long take two constant pool entries
- src_i += 2;
- dest_i += 2;
- break;
-
- default:
- // all others take one constant pool entry
- src_i++;
- dest_i++;
- break;
- }
- }
+void ConstantPool::copy_operands(constantPoolHandle from_cp,
+ constantPoolHandle to_cp,
+ TRAPS) {
int from_oplen = operand_array_length(from_cp->operands());
int old_oplen = operand_array_length(to_cp->operands());
@@ -1179,8 +1156,39 @@
to_cp->set_operands(new_operands);
}
}
+} // end copy_operands()
-} // end copy_cp_to()
+
+// Copy this constant pool's entries at start_i to end_i (inclusive)
+// to the constant pool to_cp's entries starting at to_i. A total of
+// (end_i - start_i) + 1 entries are copied.
+void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i,
+ constantPoolHandle to_cp, int to_i, TRAPS) {
+
+
+ int dest_i = to_i; // leave original alone for debug purposes
+
+ for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) {
+ copy_entry_to(from_cp, src_i, to_cp, dest_i, CHECK);
+
+ switch (from_cp->tag_at(src_i).value()) {
+ case JVM_CONSTANT_Double:
+ case JVM_CONSTANT_Long:
+ // double and long take two constant pool entries
+ src_i += 2;
+ dest_i += 2;
+ break;
+
+ default:
+ // all others take one constant pool entry
+ src_i++;
+ dest_i++;
+ break;
+ }
+ }
+ copy_operands(from_cp, to_cp, CHECK);
+
+} // end copy_cp_to_impl()
// Copy this constant pool's entry at from_i to the constant pool
--- a/hotspot/src/share/vm/oops/constantPool.hpp Wed Jan 23 10:34:29 2013 -0500
+++ b/hotspot/src/share/vm/oops/constantPool.hpp Thu Jan 24 22:13:32 2013 -0800
@@ -781,6 +781,7 @@
}
static void copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS);
static void copy_entry_to(constantPoolHandle from_cp, int from_i, constantPoolHandle to_cp, int to_i, TRAPS);
+ static void copy_operands(constantPoolHandle from_cp, constantPoolHandle to_cp, TRAPS);
int find_matching_entry(int pattern_i, constantPoolHandle search_cp, TRAPS);
int version() const { return _saved._version; }
void set_version(int version) { _saved._version = version; }
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed Jan 23 10:34:29 2013 -0500
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Thu Jan 24 22:13:32 2013 -0800
@@ -1122,6 +1122,8 @@
}
} // end for each old_cp entry
+ ConstantPool::copy_operands(old_cp, *merge_cp_p, CHECK_0);
+
// We don't need to sanity check that *merge_cp_length_p is within
// *merge_cp_p bounds since we have the minimum on-entry check above.
(*merge_cp_length_p) = old_i;
@@ -1305,8 +1307,12 @@
_index_map_count = 0;
_index_map_p = new intArray(scratch_cp->length(), -1);
+ // reference to the cp holder is needed for copy_operands()
+ merge_cp->set_pool_holder(scratch_class());
bool result = merge_constant_pools(old_cp, scratch_cp, &merge_cp,
&merge_cp_length, THREAD);
+ merge_cp->set_pool_holder(NULL);
+
if (!result) {
// The merge can fail due to memory allocation failure or due
// to robustness checks.
@@ -2380,13 +2386,14 @@
assert(version != 0, "sanity check");
smaller_cp->set_version(version);
+ // attach klass to new constant pool
+ // reference to the cp holder is needed for copy_operands()
+ smaller_cp->set_pool_holder(scratch_class());
+
scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD);
scratch_cp = smaller_cp;
// attach new constant pool to klass
- scratch_cp->set_pool_holder(scratch_class());
-
- // attach klass to new constant pool
scratch_class->set_constants(scratch_cp());
int i; // for portability