1.1 --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed Apr 24 15:57:17 2013 -0700 1.2 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Thu Apr 25 03:58:53 2013 -0700 1.3 @@ -415,20 +415,26 @@ 1.4 // this is an indirect CP entry so it needs special handling 1.5 case JVM_CONSTANT_InvokeDynamic: 1.6 { 1.7 - // TBD: cross-checks and possible extra appends into CP and bsm operands 1.8 - // are needed as well. This issue is tracked by a separate bug 8007037. 1.9 - int bss_idx = scratch_cp->invoke_dynamic_bootstrap_specifier_index(scratch_i); 1.10 - 1.11 - int ref_i = scratch_cp->invoke_dynamic_name_and_type_ref_index_at(scratch_i); 1.12 - int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p, 1.13 + // Index of the bootstrap specifier in the operands array 1.14 + int old_bs_i = scratch_cp->invoke_dynamic_bootstrap_specifier_index(scratch_i); 1.15 + int new_bs_i = find_or_append_operand(scratch_cp, old_bs_i, merge_cp_p, 1.16 + merge_cp_length_p, THREAD); 1.17 + // The bootstrap method NameAndType_info index 1.18 + int old_ref_i = scratch_cp->invoke_dynamic_name_and_type_ref_index_at(scratch_i); 1.19 + int new_ref_i = find_or_append_indirect_entry(scratch_cp, old_ref_i, merge_cp_p, 1.20 merge_cp_length_p, THREAD); 1.21 - if (new_ref_i != ref_i) { 1.22 + if (new_bs_i != old_bs_i) { 1.23 RC_TRACE(0x00080000, 1.24 - ("InvokeDynamic entry@%d name_and_type ref_index change: %d to %d", 1.25 - *merge_cp_length_p, ref_i, new_ref_i)); 1.26 + ("InvokeDynamic entry@%d bootstrap_method_attr_index change: %d to %d", 1.27 + *merge_cp_length_p, old_bs_i, new_bs_i)); 1.28 } 1.29 - 1.30 - (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, bss_idx, new_ref_i); 1.31 + if (new_ref_i != old_ref_i) { 1.32 + RC_TRACE(0x00080000, 1.33 + ("InvokeDynamic entry@%d name_and_type_index change: %d to %d", 1.34 + *merge_cp_length_p, old_ref_i, new_ref_i)); 1.35 + } 1.36 + 1.37 + (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, new_bs_i, new_ref_i); 1.38 if (scratch_i != *merge_cp_length_p) { 1.39 // The new entry in *merge_cp_p is at a different index than 1.40 // the new entry in scratch_cp so we need to map the index values. 1.41 @@ -492,6 +498,105 @@ 1.42 } // end find_or_append_indirect_entry() 1.43 1.44 1.45 +// Append a bootstrap specifier into the merge_cp operands that is semantically equal 1.46 +// to the scratch_cp operands bootstrap specifier passed by the old_bs_i index. 1.47 +// Recursively append new merge_cp entries referenced by the new bootstrap specifier. 1.48 +void VM_RedefineClasses::append_operand(constantPoolHandle scratch_cp, int old_bs_i, 1.49 + constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) { 1.50 + 1.51 + int old_ref_i = scratch_cp->operand_bootstrap_method_ref_index_at(old_bs_i); 1.52 + int new_ref_i = find_or_append_indirect_entry(scratch_cp, old_ref_i, merge_cp_p, 1.53 + merge_cp_length_p, THREAD); 1.54 + if (new_ref_i != old_ref_i) { 1.55 + RC_TRACE(0x00080000, 1.56 + ("operands entry@%d bootstrap method ref_index change: %d to %d", 1.57 + _operands_cur_length, old_ref_i, new_ref_i)); 1.58 + } 1.59 + 1.60 + Array<u2>* merge_ops = (*merge_cp_p)->operands(); 1.61 + int new_bs_i = _operands_cur_length; 1.62 + // We have _operands_cur_length == 0 when the merge_cp operands is empty yet. 1.63 + // However, the operand_offset_at(0) was set in the extend_operands() call. 1.64 + int new_base = (new_bs_i == 0) ? (*merge_cp_p)->operand_offset_at(0) 1.65 + : (*merge_cp_p)->operand_next_offset_at(new_bs_i - 1); 1.66 + int argc = scratch_cp->operand_argument_count_at(old_bs_i); 1.67 + 1.68 + ConstantPool::operand_offset_at_put(merge_ops, _operands_cur_length, new_base); 1.69 + merge_ops->at_put(new_base++, new_ref_i); 1.70 + merge_ops->at_put(new_base++, argc); 1.71 + 1.72 + for (int i = 0; i < argc; i++) { 1.73 + int old_arg_ref_i = scratch_cp->operand_argument_index_at(old_bs_i, i); 1.74 + int new_arg_ref_i = find_or_append_indirect_entry(scratch_cp, old_arg_ref_i, merge_cp_p, 1.75 + merge_cp_length_p, THREAD); 1.76 + merge_ops->at_put(new_base++, new_arg_ref_i); 1.77 + if (new_arg_ref_i != old_arg_ref_i) { 1.78 + RC_TRACE(0x00080000, 1.79 + ("operands entry@%d bootstrap method argument ref_index change: %d to %d", 1.80 + _operands_cur_length, old_arg_ref_i, new_arg_ref_i)); 1.81 + } 1.82 + } 1.83 + if (old_bs_i != _operands_cur_length) { 1.84 + // The bootstrap specifier in *merge_cp_p is at a different index than 1.85 + // that in scratch_cp so we need to map the index values. 1.86 + map_operand_index(old_bs_i, new_bs_i); 1.87 + } 1.88 + _operands_cur_length++; 1.89 +} // end append_operand() 1.90 + 1.91 + 1.92 +int VM_RedefineClasses::find_or_append_operand(constantPoolHandle scratch_cp, 1.93 + int old_bs_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) { 1.94 + 1.95 + int new_bs_i = old_bs_i; // bootstrap specifier index 1.96 + bool match = (old_bs_i < _operands_cur_length) && 1.97 + scratch_cp->compare_operand_to(old_bs_i, *merge_cp_p, old_bs_i, THREAD); 1.98 + 1.99 + if (!match) { 1.100 + // forward reference in *merge_cp_p or not a direct match 1.101 + int found_i = scratch_cp->find_matching_operand(old_bs_i, *merge_cp_p, 1.102 + _operands_cur_length, THREAD); 1.103 + if (found_i != -1) { 1.104 + guarantee(found_i != old_bs_i, "compare_operand_to() and find_matching_operand() disagree"); 1.105 + // found a matching operand somewhere else in *merge_cp_p so just need a mapping 1.106 + new_bs_i = found_i; 1.107 + map_operand_index(old_bs_i, found_i); 1.108 + } else { 1.109 + // no match found so we have to append this bootstrap specifier to *merge_cp_p 1.110 + append_operand(scratch_cp, old_bs_i, merge_cp_p, merge_cp_length_p, THREAD); 1.111 + new_bs_i = _operands_cur_length - 1; 1.112 + } 1.113 + } 1.114 + return new_bs_i; 1.115 +} // end find_or_append_operand() 1.116 + 1.117 + 1.118 +void VM_RedefineClasses::finalize_operands_merge(constantPoolHandle merge_cp, TRAPS) { 1.119 + if (merge_cp->operands() == NULL) { 1.120 + return; 1.121 + } 1.122 + // Shrink the merge_cp operands 1.123 + merge_cp->shrink_operands(_operands_cur_length, CHECK); 1.124 + 1.125 + if (RC_TRACE_ENABLED(0x00040000)) { 1.126 + // don't want to loop unless we are tracing 1.127 + int count = 0; 1.128 + for (int i = 1; i < _operands_index_map_p->length(); i++) { 1.129 + int value = _operands_index_map_p->at(i); 1.130 + if (value != -1) { 1.131 + RC_TRACE_WITH_THREAD(0x00040000, THREAD, 1.132 + ("operands_index_map[%d]: old=%d new=%d", count, i, value)); 1.133 + count++; 1.134 + } 1.135 + } 1.136 + } 1.137 + // Clean-up 1.138 + _operands_index_map_p = NULL; 1.139 + _operands_cur_length = 0; 1.140 + _operands_index_map_count = 0; 1.141 +} // end finalize_operands_merge() 1.142 + 1.143 + 1.144 jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions( 1.145 instanceKlassHandle the_class, 1.146 instanceKlassHandle scratch_class) { 1.147 @@ -765,6 +870,31 @@ 1.148 } // end find_new_index() 1.149 1.150 1.151 +// Find new bootstrap specifier index value for old bootstrap specifier index 1.152 +// value by seaching the index map. Returns unused index (-1) if there is 1.153 +// no mapped value for the old bootstrap specifier index. 1.154 +int VM_RedefineClasses::find_new_operand_index(int old_index) { 1.155 + if (_operands_index_map_count == 0) { 1.156 + // map is empty so nothing can be found 1.157 + return -1; 1.158 + } 1.159 + 1.160 + if (old_index == -1 || old_index >= _operands_index_map_p->length()) { 1.161 + // The old_index is out of range so it is not mapped. 1.162 + // This should not happen in regular constant pool merging use. 1.163 + return -1; 1.164 + } 1.165 + 1.166 + int value = _operands_index_map_p->at(old_index); 1.167 + if (value == -1) { 1.168 + // the old_index is not mapped 1.169 + return -1; 1.170 + } 1.171 + 1.172 + return value; 1.173 +} // end find_new_operand_index() 1.174 + 1.175 + 1.176 // Returns true if the current mismatch is due to a resolved/unresolved 1.177 // class pair. Otherwise, returns false. 1.178 bool VM_RedefineClasses::is_unresolved_class_mismatch(constantPoolHandle cp1, 1.179 @@ -1014,6 +1144,25 @@ 1.180 } // end map_index() 1.181 1.182 1.183 +// Map old_index to new_index as needed. 1.184 +void VM_RedefineClasses::map_operand_index(int old_index, int new_index) { 1.185 + if (find_new_operand_index(old_index) != -1) { 1.186 + // old_index is already mapped 1.187 + return; 1.188 + } 1.189 + 1.190 + if (old_index == new_index) { 1.191 + // no mapping is needed 1.192 + return; 1.193 + } 1.194 + 1.195 + _operands_index_map_p->at_put(old_index, new_index); 1.196 + _operands_index_map_count++; 1.197 + 1.198 + RC_TRACE(0x00040000, ("mapped bootstrap specifier at index %d to %d", old_index, new_index)); 1.199 +} // end map_index() 1.200 + 1.201 + 1.202 // Merge old_cp and scratch_cp and return the results of the merge via 1.203 // merge_cp_p. The number of entries in *merge_cp_p is returned via 1.204 // merge_cp_length_p. The entries in old_cp occupy the same locations 1.205 @@ -1086,6 +1235,7 @@ 1.206 } // end for each old_cp entry 1.207 1.208 ConstantPool::copy_operands(old_cp, *merge_cp_p, CHECK_0); 1.209 + (*merge_cp_p)->extend_operands(scratch_cp, CHECK_0); 1.210 1.211 // We don't need to sanity check that *merge_cp_length_p is within 1.212 // *merge_cp_p bounds since we have the minimum on-entry check above. 1.213 @@ -1198,6 +1348,8 @@ 1.214 CHECK_0); 1.215 } 1.216 1.217 + finalize_operands_merge(*merge_cp_p, THREAD); 1.218 + 1.219 RC_TRACE_WITH_THREAD(0x00020000, THREAD, 1.220 ("after pass 1b: merge_cp_len=%d, scratch_i=%d, index_map_len=%d", 1.221 *merge_cp_length_p, scratch_i, _index_map_count)); 1.222 @@ -1270,6 +1422,11 @@ 1.223 _index_map_count = 0; 1.224 _index_map_p = new intArray(scratch_cp->length(), -1); 1.225 1.226 + _operands_cur_length = ConstantPool::operand_array_length(old_cp->operands()); 1.227 + _operands_index_map_count = 0; 1.228 + _operands_index_map_p = new intArray( 1.229 + ConstantPool::operand_array_length(scratch_cp->operands()), -1); 1.230 + 1.231 // reference to the cp holder is needed for copy_operands() 1.232 merge_cp->set_pool_holder(scratch_class()); 1.233 bool result = merge_constant_pools(old_cp, scratch_cp, &merge_cp, 1.234 @@ -1400,7 +1557,6 @@ 1.235 return true; 1.236 } // end rewrite_cp_refs() 1.237 1.238 - 1.239 // Rewrite constant pool references in the methods. 1.240 bool VM_RedefineClasses::rewrite_cp_refs_in_methods( 1.241 instanceKlassHandle scratch_class, TRAPS) {